कास्टिंग और जबरदस्ती में क्या अंतर है?


85

मैंने देखा है कि दोनों शर्तों को विभिन्न ऑनलाइन स्पष्टीकरणों में लगभग परस्पर उपयोग किया गया है, और मैंने जिन पाठ्य पुस्तकों की सलाह ली है, वे भी भेद के बारे में पूरी तरह स्पष्ट नहीं हैं।

क्या शायद अंतर स्पष्ट करने का एक सरल और सरल तरीका है जो आप लोग जानते हैं?

प्रकार रूपांतरण (कभी-कभी टाइप कास्ट के रूप में भी जाना जाता है )

एक संदर्भ में एक प्रकार के मूल्य का उपयोग करने के लिए जो दूसरे की अपेक्षा करता है।

गैर-परिवर्तित प्रकार की कास्ट (कभी-कभी प्रकार वाक्य के रूप में जाना जाता है )

एक परिवर्तन जो अंतर्निहित बिट्स को परिवर्तित नहीं करता है।

बलात्कार

प्रक्रिया जिसके द्वारा एक संकलक स्वचालित रूप से एक प्रकार के मूल्य को दूसरे प्रकार के मूल्य में परिवर्तित करता है, जब आसपास के संदर्भ द्वारा उस दूसरे प्रकार की आवश्यकता होती है।


जवाबों:


114

प्रकार रूपांतरण :

शब्द रूपांतरण या तो स्पष्ट रूप से या एक डेटा प्रकार से दूसरे में मान बदलने के लिए संदर्भित करता है, जैसे 16-बिट पूर्णांक से 32-बिट पूर्णांक।

एक अंतर्निहित रूपांतरण को निरूपित करने के लिए जबरदस्ती शब्द का उपयोग किया जाता है।

कास्ट शब्द आम तौर पर एक स्पष्ट प्रकार के रूपांतरण (एक अंतर्निहित रूपांतरण के विपरीत) को संदर्भित करता है, भले ही यह बिट-पैटर्न या वास्तविक रूपांतरण की फिर से व्याख्या हो।

तो, जबरदस्ती निहित है, डाली स्पष्ट है, और रूपांतरण उनमें से कोई भी है।


कुछ उदाहरण ( उसी स्रोत से ):

जबरदस्ती (निहित):

double  d;
int     i;
if (d > i)      d = i;

कास्ट (स्पष्ट):

double da = 3.3;
double db = 3.3;
double dc = 3.4;
int result = (int)da + (int)db + (int)dc; //result == 9

क्या यह "अंतर्निहित जबरदस्ती" को बेमानी बना देगा? यहाँ नोट "निहित ज़बरदस्ती" और "स्पष्ट ज़बरदस्ती" दोनों का उपयोग करता है
डेव कज़िन्यू

1
निहित रूपांतरण केवल तब किया जा सकता है जब आप सटीक नहीं खो रहे हैं या समझ में नहीं आता है (उदाहरण: इंट -> डबल)। अधिकांश आधुनिक भाषा में, आप डबल-> इंट नहीं कर सकते क्योंकि आप सटीक खो देंगे। प्रकार की जबरदस्ती के साथ, यह "समस्या" नहीं है।
मैक्सिम रूइलर

यह उत्तर CIL के लिए ecma 335 में परिभाषित विशिष्टताओं के साथ संरेखित नहीं है। मैंने अपने उत्तर में उदाहरणों के साथ विनिर्देश परिभाषा रखी।
पी। ब्रायन। मैके

24

जैसा कि आप ध्यान दें, Usages अलग-अलग होते हैं।

मेरे निजी उपयोग हैं:

  • "कास्ट" कास्ट ऑपरेटर का उपयोग है । एक कास्ट ऑपरेटर कंपाइलर को निर्देश देता है कि या तो (1) यह एक्सप्रेशन दिए गए प्रकार का नहीं है, लेकिन मैं आपसे वादा करता हूं कि रनटाइम के दौरान वैल्यू उस टाइप की होगी; संकलक अभिव्यक्ति को दिए गए प्रकार के रूप में माना जाता है, और रनटाइम एक त्रुटि उत्पन्न करेगा यदि यह नहीं है, या (2) अभिव्यक्ति पूरी तरह से एक अलग प्रकार की है, लेकिन उदाहरणों को जोड़ने के लिए एक प्रसिद्ध तरीका है कास्ट-टू-टाइप के उदाहरणों के साथ अभिव्यक्ति का प्रकार। संकलक को कोड उत्पन्न करने के लिए निर्देश दिया जाता है जो रूपांतरण करता है। चौकस पाठक ध्यान देगा कि ये विपरीत हैं, जो मुझे लगता है कि एक साफ-सुथरी चाल है।

  • एक "रूपांतरण" एक ऑपरेशन है जिसके द्वारा एक प्रकार के मूल्य को दूसरे प्रकार के मूल्य के रूप में माना जाता है - आमतौर पर एक अलग प्रकार, हालांकि "पहचान रूपांतरण" अभी भी एक रूपांतरण है, तकनीकी रूप से बोल रहा है। रूपांतरण "प्रतिनिधित्व परिवर्तन" हो सकता है, उदाहरण के लिए डबल करने के लिए, या यह स्ट्रिंग से ऑब्जेक्ट की तरह "प्रतिनिधित्व संरक्षण" हो सकता है। रूपांतरण "निहित" हो सकते हैं, जिनमें किसी कलाकार या "स्पष्ट" की आवश्यकता नहीं होती है, जिन्हें किसी कलाकार की आवश्यकता होती है।

  • एक "जबरदस्ती" एक प्रतिनिधित्व-बदलते निहित रूपांतरण है।


1
मुझे लगता है कि इस उत्तर का पहला वाक्य सबसे महत्वपूर्ण है। विभिन्न भाषाएं इन शब्दों का उपयोग काफी अलग चीजों के लिए करती हैं। हास्केल में, उदाहरण के लिए, एक "जबरदस्ती" प्रतिनिधित्व को कभी नहीं बदलता है; एक सुरक्षित बलात्कार, Data.Coerce.coerce :: Coercible a b => a -> bएक ही प्रतिनिधित्व के लिए सिद्ध प्रकारों के लिए काम करता है; Unsafe.Coerce.unsafeCoerce :: a -> bकिसी भी दो प्रकार के लिए काम करता है (और अगर आप इसे गलत उपयोग करते हैं तो दानव आपकी नाक से बाहर निकलेंगे)।
डेफ़र

@ दिलचस्प डेटा बिंदु, धन्यवाद! मैं ध्यान देता हूं कि सी # कल्पना "जबरदस्ती" को परिभाषित नहीं करती है; मेरा सुझाव सिर्फ वही है जो मेरा व्यक्तिगत रूप से मतलब है। यह देखते हुए कि यह शब्द खराब तरीके से परिभाषित है, मैं आमतौर पर इससे बचता हूं।
एरिक लिपर्ट

8

कास्टिंग एक ऐसी प्रक्रिया है जिसके द्वारा आप एक वस्तु प्रकार को दूसरे प्रकार के रूप में मानते हैं, एक वस्तु को दूसरी वस्तु में परिवर्तित कर रहा है।

ध्यान दें कि पूर्व प्रक्रिया में कोई रूपांतरण शामिल नहीं है, आपके पास एक प्रकार है जिसे आप किसी अन्य के रूप में मान सकते हैं, उदाहरण के लिए, आपके पास 3 अलग-अलग ऑब्जेक्ट हैं जो आधार प्रकार से प्राप्त होते हैं, और आपके पास एक विधि है जो इसे ले जाएगी आधार प्रकार, किसी भी बिंदु पर, यदि आप विशिष्ट बच्चे के प्रकार को जानते हैं, तो आप इसे उस वस्तु पर कास्ट कर सकते हैं और उस वस्तु के सभी विशिष्ट तरीकों और गुणों का उपयोग कर सकते हैं और यह वस्तु का नया उदाहरण नहीं बनाएगा।

दूसरी ओर, नए प्रकार की स्मृति में नए ऑब्जेक्ट के निर्माण के लिए जोर-जबरदस्ती का मतलब है और फिर मूल प्रकार को नए पर कॉपी किया जाएगा, दोनों वस्तुओं को स्मृति में छोड़ देगा (जब तक कि कचरा कलेक्टर या तो दूर नहीं ले जाता है, या दोनों) ।

एक उदाहरण के रूप में निम्नलिखित कोड पर विचार करें:

class baseClass {}
class childClass : baseClass {}
class otherClass {}

public void doSomethingWithBase(baseClass item) {}

public void mainMethod()
{
    var obj1 = new baseClass();
    var obj2 = new childClass();
    var obj3 = new otherClass();

    doSomethingWithBase(obj1); //not a problem, obj1 is already of type baseClass
    doSomethingWithBase(obj2); //not a problem, obj2 is implicitly casted to baseClass
    doSomethingWithBase(obj3); //won't compile without additional code
}
  • obj1 को बिना किसी कास्टिंग या कॉर्किंग (रूपांतरण) के पास किया जाता है क्योंकि यह पहले से ही एक ही प्रकार का है baseClass
  • obj2 को मूल रूप से आधार बनाया गया है, जिसका अर्थ है कि नई वस्तु का निर्माण नहीं है क्योंकि obj2 पहले से ही हो सकता है baseClass
  • obj3 जरूरतों आधार के लिए किसी भी तरह परिवर्तित किया है, तो आप से परिवर्तित करने के लिए अपनी खुद की विधि प्रदान करना होगा otherClassकरने के लिए baseClassहै, जो प्रकार baseClass की एक नई वस्तु बनाने और obj3 से डेटा कॉपी करके यह भरने शामिल होगी।

एक अच्छा उदाहरण कन्वर्ट सी # वर्ग है जहां यह विभिन्न प्रकारों के बीच परिवर्तित करने के लिए कस्टम कोड प्रदान करता है।


3
एक उदाहरण उस भेद को स्पष्ट करने में मदद करेगा जिसे आप बनाने की कोशिश कर रहे हैं।
ओलिवर चार्ल्सवर्थ

2

कास्टिंग वस्तुओं के प्रकार को संरक्षित करता है। जबरदस्ती नहीं करता।

ज़बरदस्ती एक प्रकार का मूल्य ले रहा है जो कि असाइनमेंट के अनुकूल नहीं है और एक प्रकार का है जो असाइनमेंट के अनुकूल है। यहाँ मैं एक ज़बरदस्त प्रदर्शन Int32करता हूँ, क्योंकि यह विरासत में नहीं मिला है Int64... इसलिए यह काम के अनुकूल नहीं है। यह एक व्यापक दबाव है (कोई डेटा नहीं खोया)। एक व्यापक दबाव उर्फ ​​एक अंतर्निहित रूपांतरण हैएक रूपांतरण रूपांतरण करता है।

void Main()
{
    System.Int32 a = 100;
    System.Int64 b = a;
    b.GetType();//The type is System.Int64.  
}

कास्टिंग आपको एक प्रकार का इलाज करने की अनुमति देता है जैसे कि यह एक अलग प्रकार का था जबकि प्रकार को संरक्षित करना भी ।

    void Main()
    {
        Derived d = new Derived();
        Base bb = d;
        //b.N();//INVALID.  Calls to the type Derived are not possible because bb is of type Base
        bb.GetType();//The type is Derived.  bb is still of type Derived despite not being able to call members of Test
    }

    class Base 
    {
        public void M() {}
    }

    class Derived: Base
    {
        public void N() {}
    }

स्रोत: जेम्स एस। मिलर द्वारा कॉमन लैंग्वेज इन्फ्रास्ट्रक्चर एनोटेट स्टैंडर्ड

अब यह विचित्र है कि कास्टिंग पर Microsoft का दस्तावेजीकरण कास्टिंग के ecma-335 विनिर्देश परिभाषा के साथ संरेखित नहीं करता है।

स्पष्ट रूपांतरण (कास्ट): स्पष्ट रूपांतरण के लिए एक कास्ट ऑपरेटर की आवश्यकता होती है। जब रूपांतरण में जानकारी खो सकती है, या जब अन्य कारणों से रूपांतरण सफल नहीं हो सकता है तब कास्टिंग की आवश्यकता होती है। विशिष्ट उदाहरणों में एक प्रकार का संख्यात्मक रूपांतरण शामिल होता है जिसमें कम सटीकता या एक छोटी सी सीमा होती है, और एक बेस क्लास उदाहरण से व्युत्पन्न वर्ग में रूपांतरण होता है।

... यह लगता है कि ज़बरदस्ती कास्टिंग नहीं है।

उदाहरण के लिए,

  object o = 1;
  int i = (int)o;//Explicit conversions require a cast operator
  i.GetType();//The type has been explicitly converted to System.Int32.  Object type is not preserved.  This meets the definition of Coercion not casting.

कौन जाने? हो सकता है कि Microsoft जाँच कर रहा हो कि क्या कोई इस सामान को पढ़ता है।


1

नीचे निम्नलिखित लेख से एक पोस्टिंग है :

जबरदस्ती और कास्टिंग के बीच अंतर अक्सर उपेक्षित होता है। मैं देख सकता हूँ क्यों; कई भाषाओं में दोनों कार्यों के लिए एक ही (या समान) वाक्य रचना और शब्दावली है। कुछ भाषाएं "कास्टिंग" के रूप में भी किसी भी रूपांतरण का उल्लेख कर सकती हैं, लेकिन निम्नलिखित स्पष्टीकरण सीटीएस में अवधारणाओं को संदर्भित करता है।

यदि आप किसी प्रकार के मान को किसी भिन्न प्रकार के स्थान पर निर्दिष्ट करने का प्रयास कर रहे हैं, तो आप नए प्रकार का मान उत्पन्न कर सकते हैं जिसका मूल के समान अर्थ है। यह ज़बरदस्ती है। ज़बरदस्ती आपको नए प्रकार का उपयोग करके एक नया मूल्य बनाने की अनुमति देता है जो किसी तरह से मूल जैसा होता है। कुछ सहकर्मी डेटा को छोड़ सकते हैं (उदाहरण के लिए int 0x12345678 को लघु 0x5678 में परिवर्तित करना), जबकि अन्य नहीं कर सकते हैं (उदाहरण के लिए int 0x00000008 को लघु 0x0008, या लंबे समय तक 0x000000000008 को कनवर्ट करना)।

याद रखें कि मान कई प्रकार के हो सकते हैं। यदि आपकी स्थिति थोड़ी अलग है, और आप केवल मूल्य के प्रकारों में से एक का चयन करना चाहते हैं, तो कास्टिंग नौकरी के लिए उपकरण है। कास्टिंग केवल इंगित करता है कि आप एक विशेष प्रकार पर काम करना चाहते हैं जिसमें एक मूल्य शामिल है।

कोड स्तर पर अंतर C # से IL तक भिन्न होता है। C # में, कास्टिंग और ज़बरदस्ती दोनों एक जैसे दिखते हैं:

static void ChangeTypes(int number, System.IO.Stream stream)
{
    long longNumber = number;
    short shortNumber = (short)number;

    IDisposable disposableStream = stream;
    System.IO.FileStream fileStream = (System.IO.FileStream)stream;
}

IL स्तर पर वे काफी अलग हैं:

ldarg.0
 conv.i8
 stloc.0

ldarg.0
 conv.i2
 stloc.1


ldarg.1
 stloc.2

ldarg.1
 castclass [mscorlib]System.IO.FileStream
 stloc.3

तार्किक स्तर के लिए, कुछ महत्वपूर्ण अंतर हैं। याद रखने के लिए जो सबसे महत्वपूर्ण है वह यह है कि जबरदस्ती एक नया मूल्य बनाता है, जबकि कास्टिंग नहीं करता है। कास्टिंग के बाद मूल मूल्य और मूल्य की पहचान समान है, जबकि एक समन्वित मूल्य की पहचान मूल मूल्य से अलग है; एक नया, अलग उदाहरण बनाता है, जबकि कास्टिंग नहीं करता है। एक कोरोलरी यह है कि कास्टिंग और मूल का परिणाम हमेशा समान होगा (दोनों पहचान और समानता में), लेकिन एक सुसंगत मूल्य मूल के बराबर हो सकता है या नहीं हो सकता है, और मूल पहचान को कभी साझा नहीं करता है।

उपरोक्त उदाहरणों में ज़बरदस्ती के निहितार्थ को देखना आसान है, क्योंकि संख्यात्मक प्रकार हमेशा मूल्य द्वारा कॉपी किए जाते हैं। जब आप संदर्भ प्रकारों के साथ काम कर रहे हों तो चीजें थोड़ी पेचीदा हो जाती हैं।

class Name : Tuple<string, string>
{
    public Name(string first, string last)
        : base(first, last)
    {
    }

    public static implicit operator string[](Name name)
    {
        return new string[] { name.Item1, name.Item2 };
    }
}

नीचे दिए गए उदाहरण में, एक रूपांतरण एक कास्ट है, जबकि दूसरा एक जबरदस्ती है।

Tuple<string, string> tuple = name;
string[] strings = name;

इन रूपांतरणों के बाद, टपल और नाम समान हैं, लेकिन तार दोनों में से किसी के बराबर नहीं हैं। आप नाम वर्ग और स्ट्रिंग [] की तुलना करने के लिए नाम वर्ग पर इक्वल्स () और ऑपरेटर == () को लागू करके स्थिति को थोड़ा बेहतर (या थोड़ा और अधिक भ्रमित) कर सकते हैं। ये ऑपरेटर तुलनात्मक समस्या को "ठीक" करेंगे, लेकिन फिर भी आपके पास दो अलग-अलग उदाहरण होंगे; स्ट्रिंग्स के किसी भी संशोधन को नाम या टपल में नहीं दिखाया जाएगा, जबकि नाम या टपल में से किसी एक में परिवर्तन नाम और टपल में परिलक्षित होगा, लेकिन स्ट्रिंग्स में नहीं।

यद्यपि ऊपर दिए गए उदाहरण का अर्थ कास्टिंग और जबरदस्ती के बीच कुछ अंतरों को स्पष्ट करना था, यह इस बात का भी एक महान उदाहरण है कि आप C # में संदर्भ प्रकारों के साथ रूपांतरण ऑपरेटरों का उपयोग करने के बारे में अत्यधिक सतर्क क्यों रहें।


1

से CLI मानक :

I.8.3.2 जबरदस्ती

कभी-कभी एक प्रकार का मान लेना वांछनीय होता है, जो किसी स्थान के लिए उपलब्ध नहीं होता है, और मान को ऐसे प्रकार में परिवर्तित कर सकता है जो असाइन करने योग्य है-स्थान के प्रकार पर। यह मूल्य के जोर के माध्यम से पूरा किया जाता है । जबरदस्ती एक विशेष प्रकार और एक वांछित प्रकार का मान लेती है और वांछित प्रकार का एक मूल्य बनाने का प्रयास करती है जिसका मूल मूल्य के बराबर अर्थ होता है। जबरदस्ती के परिणामस्वरूप प्रतिनिधित्व परिवर्तन के साथ-साथ परिवर्तन भी हो सकते हैं; इसलिए जबरदस्ती जरूरी वस्तु पहचान को संरक्षित नहीं करता है।

दो तरह के ज़बरदस्ती हैं: चौड़ा करना , जो कभी भी जानकारी नहीं खोता है, और संकीर्णता , जिसमें जानकारी खो सकती है। एक चौड़ीकरण जबरदस्ती का एक उदाहरण एक मूल्य है जो कि 32-बिट हस्ताक्षरित पूर्णांक है जो 64-बिट हस्ताक्षरित पूर्णांक है। एक संकुचित ज़बरदस्ती का एक उदाहरण रिवर्स है: एक 64-बिट हस्ताक्षरित पूर्णांक को 32-बिट हस्ताक्षरित पूर्णांक के लिए बाध्य करना। प्रोग्रामिंग भाषाओं में अक्सर अंतर्निहित रूपांतरणों के रूप में चौड़ीकरण सहूलियतों को लागू किया जाता है , जबकि संकीर्ण जमावटों को आमतौर पर एक स्पष्ट रूपांतरण की आवश्यकता होती है ।

कुछ जोर सीधे अंतर्निहित प्रकारों पर वीईएस के संचालन में बनाया गया है (देखें .1I.12.1)। अन्य सभी जोर-जबरदस्ती का अनुरोध किया जाएगा। बिल्ट-इन प्रकारों के लिए, सीटीएस ऑपरेशन सेमेंटिक्स के अनुसार रनटाइम चेक या ट्रंकेशन के साथ कोई रनटाइम चेक के साथ चौड़ीकरण को कम करने के लिए ऑपरेशन प्रदान करता है।

I.8.3.3 कास्टिंग

चूंकि एक मूल्य एक से अधिक प्रकार का हो सकता है, इसलिए मूल्य के उपयोग को स्पष्ट रूप से पहचानने की जरूरत है कि इसके कौन से प्रकार का उपयोग किया जा रहा है। चूँकि मान टाइप किए गए स्थानों से पढ़े जाते हैं, इसलिए जिस प्रकार का मूल्य प्रयोग किया जाता है वह उस स्थान का प्रकार है जहाँ से मान पढ़ा गया था। यदि एक अलग प्रकार का उपयोग किया जाना है, तो मूल्य इसके अन्य प्रकारों में से एक में डाला जाता है। आमतौर पर कास्टिंग एक संकलित समय ऑपरेशन है, लेकिन यदि संकलक सांख्यिकीय रूप से यह नहीं जान सकता है कि मूल्य लक्ष्य प्रकार का है, तो रनटाइम कास्ट चेक किया जाता है। जबरदस्ती के विपरीत, एक कलाकार कभी भी वास्तविक प्रकार की वस्तु नहीं बदलता है और न ही यह प्रतिनिधित्व को बदलता है। कास्टिंग वस्तुओं की पहचान को बनाए रखता है।

उदाहरण के लिए, किसी विशेष इंटरफ़ेस के मान के रूप में टाइप किए गए स्थान से पढ़े गए मान को कास्टिंग करते समय रनटाइम चेक की आवश्यकता हो सकती है। चूंकि एक अंतरफलक मूल्य का अधूरा विवरण होता है, इसलिए उस मूल्य को एक अलग इंटरफ़ेस प्रकार का होना आमतौर पर रनटाइम कास्ट चेक में परिणाम देगा।


1

विकिपीडिया के अनुसार,

कंप्यूटर विज्ञान में, टाइप कन्वर्शन, टाइप कास्टिंग, टाइप कॉर्शन और टाइप बाजीगरी एक अभिव्यक्ति को एक डेटा प्रकार से दूसरे में बदलने के विभिन्न तरीके हैं।

टाइप कास्टिंग और टाइप कॉर्शन के बीच अंतर इस प्रकार है:

           TYPE CASTING           |                   TYPE COERCION
                                  |
1. Explicit i.e., done by user    | 1. Implicit i.e., done by the compiler
                                  |
2. Types:                         | 2. Type:
    Static (done at compile time) |     Widening (conversion to higher data 
                                  |     type)
    Dynamic (done at run time)    |     Narrowing (conversion to lower data 
                                  |     type)
                                  |
3. Casting never changes the      | 3. Coercion can result in representation 
   the actual type of object      |    as well as type change.
   nor representation.            |

नोट : कास्टिंग रूपांतरण नहीं है। यह सिर्फ एक प्रक्रिया है जिसके द्वारा हम एक वस्तु प्रकार को दूसरे प्रकार के रूप में मानते हैं। इसलिए, वास्तविक प्रकार की वस्तु, साथ ही प्रतिनिधित्व, कास्टिंग के दौरान नहीं बदला जाता है।

मैं @ PedroC88 के शब्दों से सहमत हूं:

दूसरी ओर, नए प्रकार की स्मृति में नए ऑब्जेक्ट के निर्माण के लिए जोर-जबरदस्ती का अर्थ है और फिर मूल प्रकार को नए पर कॉपी किया जाएगा, दोनों वस्तुओं को स्मृति में छोड़ देगा (जब तक कि कचरा कलेक्टर या तो दूर नहीं ले जाता है, या दोनों) ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.