क्यों पर्दे के पीछे टंकण है? यह बहुत तेज़ और सुरक्षित है ... लगभग जादुई!


128

चेतावनी: यह सवाल थोड़ा सा है ... धार्मिक प्रोग्रामर हमेशा अच्छी प्रथाओं का पालन करते हैं, कृपया इसे न पढ़ें। :)

क्या किसी को पता है कि TypedReference का उपयोग इतना हतोत्साहित ( संक्षेप में, प्रलेखन की कमी से) क्यों होता है?

मैंने इसके लिए बहुत उपयोग किए हैं, जैसे कि फ़ंक्शंस के माध्यम से जेनेरिक पैरामीटर पास करना, जो कि जेनेरिक नहीं होना चाहिए (जब एक objectऑवरकल या धीमी गति से उपयोग किया जा सकता है, यदि आपको एक वैल्यू टाइप की आवश्यकता है), तो जब आपको एक अपारदर्शी सूचक की आवश्यकता हो, या जब आपको किसी ऐरे के तत्व को जल्दी से एक्सेस करने की आवश्यकता होती है, जिसके स्पेक्स आपको रनटाइम (उपयोग करने Array.InternalGetReference) में मिलते हैं । चूंकि सीएलआर इस प्रकार के गलत उपयोग की अनुमति नहीं देता है, इसलिए इसे हतोत्साहित क्यों किया जाता है? यह असुरक्षित या कुछ भी नहीं लगता ...


अन्य उपयोग जिन्हें मैंने पाया है TypedReference:

"सी # में सक्रिय जेनरिक (यह प्रकार-सुरक्षित है):

static void foo<T>(ref T value)
{
    //This is the ONLY way to treat value as int, without boxing/unboxing objects
    if (value is int)
    { __refvalue(__makeref(value), int) = 1; }
    else { value = default(T); }
}

लेखन कोड जो जेनेरिक पॉइंटर्स के साथ काम करता है ( यदि इसका गलत उपयोग किया जाता है तो बहुत असुरक्षित है, लेकिन सही तरीके से उपयोग किए जाने पर तेज़ और सुरक्षित):

//This bypasses the restriction that you can't have a pointer to T,
//letting you write very high-performance generic code.
//It's dangerous if you don't know what you're doing, but very worth if you do.
static T Read<T>(IntPtr address)
{
    var obj = default(T);
    var tr = __makeref(obj);

    //This is equivalent to shooting yourself in the foot
    //but it's the only high-perf solution in some cases
    //it sets the first field of the TypedReference (which is a pointer)
    //to the address you give it, then it dereferences the value.
    //Better be 10000% sure that your type T is unmanaged/blittable...
    unsafe { *(IntPtr*)(&tr) = address; }

    return __refvalue(tr, T);
}

निर्देश का एक विधि संस्करण लिखना sizeof, जो कभी-कभी उपयोगी हो सकता है:

static class ArrayOfTwoElements<T> { static readonly Value = new T[2]; }

static uint SizeOf<T>()
{
    unsafe 
    {
        TypedReference
            elem1 = __makeref(ArrayOfTwoElements<T>.Value[0] ),
            elem2 = __makeref(ArrayOfTwoElements<T>.Value[1] );
        unsafe
        { return (uint)((byte*)*(IntPtr*)(&elem2) - (byte*)*(IntPtr*)(&elem1)); }
    }
}

एक ऐसी विधि लिखना जो एक "राज्य" पैरामीटर पास करता है जो मुक्केबाजी से बचना चाहता है:

static void call(Action<int, TypedReference> action, TypedReference state)
{
    //Note: I could've said "object" instead of "TypedReference",
    //but if I had, then the user would've had to box any value types
    try
    {
        action(0, state);
    }
    finally { /*Do any cleanup needed*/ }
}

तो इस तरह के "हतोत्साहित" (प्रलेखन की कमी के कारण) का उपयोग क्यों किया जाता है? कोई विशेष सुरक्षा कारण? यह पूरी तरह से सुरक्षित और सत्यापन योग्य लगता है अगर यह संकेतकर्ताओं (जो किसी भी तरह से सुरक्षित या सत्यापन योग्य नहीं है) के साथ मिश्रित नहीं है ...


अपडेट करें:

यह दिखाने के लिए कि सैंपल कोड, वास्तव में, TypedReferenceदो बार तेज (या अधिक) हो सकता है:

using System;
using System.Collections.Generic;
static class Program
{
    static void Set1<T>(T[] a, int i, int v)
    { __refvalue(__makeref(a[i]), int) = v; }

    static void Set2<T>(T[] a, int i, int v)
    { a[i] = (T)(object)v; }

    static void Main(string[] args)
    {
        var root = new List<object>();
        var rand = new Random();
        for (int i = 0; i < 1024; i++)
        { root.Add(new byte[rand.Next(1024 * 64)]); }
        //The above code is to put just a bit of pressure on the GC

        var arr = new int[5];
        int start;
        const int COUNT = 40000000;

        start = Environment.TickCount;
        for (int i = 0; i < COUNT; i++)
        { Set1(arr, 0, i); }
        Console.WriteLine("Using TypedReference:  {0} ticks",
                          Environment.TickCount - start);
        start = Environment.TickCount;
        for (int i = 0; i < COUNT; i++)
        { Set2(arr, 0, i); }
        Console.WriteLine("Using boxing/unboxing: {0} ticks",
                          Environment.TickCount - start);

        //Output Using TypedReference:  156 ticks
        //Output Using boxing/unboxing: 484 ticks
    }
}

(संपादित करें: मैंने ऊपर बेंचमार्क को संपादित किया, क्योंकि पोस्ट के अंतिम संस्करण ने कोड के डिबग संस्करण का उपयोग किया था [मैं इसे जारी करने के लिए बदलना भूल गया], और जीसी पर कोई दबाव नहीं डाला। यह संस्करण थोड़ा अधिक यथार्थवादी है, और मेरे सिस्टम पर, यह TypedReferenceऔसत से तीन गुना अधिक तेज है ।)


जब मैं आपका उदाहरण चलाता हूं तो मुझे पूरी तरह से अलग परिणाम मिलते हैं। TypedReference: 203 ticks, boxing/unboxing: 31 ticks। इससे कोई फर्क नहीं पड़ता कि मैं क्या कोशिश करता हूं (टाइमिंग करने के अलग-अलग तरीकों सहित) बॉक्सिंग / अनबॉक्सिंग अभी भी मेरे सिस्टम पर तेज है।
सेप

1
@ सिफ: मैंने आपकी टिप्पणी को देखा। यह बहुत दिलचस्प है - यह x64 पर तेज़ लगता है, लेकिन x86 पर धीमा है। अजीब ...
user541686

1
मैंने अभी-अभी .NET 4.5 के तहत अपनी x64 मशीन पर उस बेंचमार्क कोड का परीक्षण किया। मैंने Environment.TickCount को Diagnostics.Stopwatch से बदल दिया और टिक के बजाय ms के साथ चला गया। मैंने प्रत्येक बिल्ड (x86, 64, Any) को तीन बार चलाया। तीन परिणामों में से सर्वश्रेष्ठ फॉलोवर्स के रूप में थे: x86: 205 / 27ms (इस बिल्ड पर 2/3 रन के लिए एक ही परिणाम) x64: 218 / 109ms Any: 205 / 27ms (इस बिल्ड पर 2/3 रन के लिए एक ही परिणाम) -all- केस बॉक्स / अनबॉक्सिंग तेज था।
kornman00

2
इन दो तथ्यों के लिए अजीब गति माप को जिम्मेदार ठहराया जा सकता है: * (T) (ऑब्जेक्ट) v वास्तव में ढेर आवंटन नहीं करता है। .NET 4+ में यह अनुकूलित है। इस पथ पर कोई आवंटन नहीं हैं, और यह बहुत तेज़ है। * Makeref का उपयोग करने के लिए चर को वास्तव में स्टैक पर आवंटित करने की आवश्यकता होती है (जबकि थोड़े बॉक्स पद्धति इसे रजिस्टरों में अनुकूलित कर सकती है)। इसके अलावा, समय को देखते हुए, मुझे लगता है कि यह बल-इनलाइन ध्वज के साथ भी इनलाइनिंग लगाता है। तो थोड़े बॉक्स में इनबिल्ट और एनग्रेस्टर होता है, जबकि मेकेरेफ एक फंक्शन कॉल करता है और स्टैक संचालित करता है
hypersw

1
टाइपराइफ कास्टिंग के मुनाफे को देखने के लिए, इसे कम तुच्छ बनाएं। उदाहरण के लिए Enum प्रकार ( int-> DockStyle) में एक अंतर्निहित प्रकार की कास्टिंग । असली के लिए यह बॉक्स, और लगभग दस गुना धीमा है।
18

जवाबों:


42

संक्षिप्त उत्तर: पोर्टेबिलिटी

जबकि __arglist, __makerefहै, और __refvalueकर रहे हैं भाषा एक्सटेंशन और सी # भाषा विशिष्टता में गैर-दस्तावेजी कर रहे हैं, उन्हें हुड के नीचे लागू करने के लिए इस्तेमाल किया निर्माणों ( varargसम्मेलन बुला, TypedReferenceप्रकार, arglist, refanytype, mkanyref, और refanyvalनिर्देश) पूरी तरह से में दर्ज कर रहे हैं CLI विशिष्टता (ECMA-335) में Vararg पुस्तकालय

वरग लाइब्रेरी में परिभाषित होने के कारण यह स्पष्ट है कि वे मुख्य रूप से चर-लंबाई तर्क सूचियों का समर्थन करने के लिए हैं और बहुत कुछ नहीं। परिवर्तनीय-तर्क सूचियों का उन प्लेटफार्मों में बहुत कम उपयोग होता है जिन्हें बाहरी सी कोड के साथ इंटरफ़ेस करने की आवश्यकता नहीं होती है जो वैरगैस का उपयोग करते हैं। इस कारण से, Varargs लाइब्रेरी किसी CLI प्रोफ़ाइल का हिस्सा नहीं है। वैध सीएलआई कार्यान्वयन वरगर्ज़ लाइब्रेरी का समर्थन नहीं करना चुन सकते हैं क्योंकि यह सीएलआई कर्नेल प्रोफ़ाइल में शामिल नहीं है:

4.1.6 वरग

Vararg सुविधा सेट चर लंबाई तर्क सूचियों और क्रम टाइप संकेत का समर्थन करता है।

यदि छोड़ा गया:vararg कॉलिंग कन्वेंशन के साथ किसी विधि को संदर्भित करने का कोई भी प्रयास या वैरग तरीकों से जुड़े हस्ताक्षर एन्कोडिंग (विभाजन II देखें) System.NotImplementedExceptionअपवाद को फेंक देंगे । सीआईएल निर्देशों का उपयोग कर के तरीके arglist, refanytype, mkrefany, और refanyvalफेंक करेगा System.NotImplementedExceptionअपवाद। अपवाद का सटीक समय निर्दिष्ट नहीं है। प्रकार को System.TypedReferenceपरिभाषित करने की आवश्यकता नहीं है।

अपडेट ( GetValueDirectटिप्पणी का जवाब ):

FieldInfo.GetValueDirectकर रहे हैं FieldInfo.SetValueDirectकर रहे हैं नहीं बेस कक्षा लाइब्रेरी का हिस्सा है। ध्यान दें कि .NET फ्रेमवर्क क्लास लाइब्रेरी और बेस क्लास लाइब्रेरी के बीच अंतर है। BCL CLI / C # के अनुरूप कार्यान्वयन के लिए आवश्यक एकमात्र चीज़ है और ECMA TR / 84 में प्रलेखित है । (वास्तव में, FieldInfoस्वयं परावर्तन पुस्तकालय का हिस्सा है और यह सीएलआई कर्नेल प्रोफ़ाइल में शामिल नहीं है)।

जैसे ही आप बीसीएल के बाहर एक विधि का उपयोग करते हैं, आप थोड़ा पोर्टेबिलिटी दे रहे हैं (और यह सिल्वरलाइट और मोनो-टच जैसे गैर- .NET CLI कार्यान्वयन के आगमन के साथ महत्वपूर्ण होता जा रहा है)। यहां तक कि अगर एक कार्यान्वयन Microsoft .NET फ्रेमवर्क कक्षा लाइब्रेरी के साथ compatiblility को बढ़ाने के लिए करना चाहता था, यह बस प्रदान कर सकता है GetValueDirectऔर SetValueDirectएक लेने के TypedReferenceबिना TypedReference(उन्हें अपने के बराबर मूल रूप से, विशेष रूप से बनाने क्रम द्वारा नियंत्रित किया objectप्रदर्शन लाभ के बिना समकक्षों)।

यदि उन्होंने इसे C # में प्रलेखित किया होता, तो इसके कम से कम कुछ निहितार्थ होते:

  1. किसी भी सुविधा की तरह, यह नई सुविधाओं के लिए एक मार्ग बन सकता है, खासकर जब से यह वास्तव में सी # के डिजाइन में फिट नहीं होता है और रनटाइम द्वारा अजीब वाक्यविन्यास एक्सटेंशन और एक प्रकार के विशेष सौंपने की आवश्यकता होती है।
  2. C # के सभी कार्यान्वयनों को किसी न किसी तरह से इस सुविधा को लागू करना पड़ता है और यह C # कार्यान्वयन के लिए आवश्यक रूप से तुच्छ / संभव नहीं है, जो CLI के शीर्ष पर बिल्कुल भी नहीं चलते हैं या Varargs के बिना CLI के शीर्ष पर चलते हैं।

4
पोर्टेबिलिटी के लिए अच्छे तर्क, +1। लेकिन क्या FieldInfo.GetValueDirectऔर FieldInfo.SetValueDirect? वे बीसीएल का हिस्सा हैं, और उन्हें आपकी ज़रूरत का उपयोग करने के लिए TypedReference, इसलिए यह मूल रूप TypedReferenceसे हमेशा परिभाषित नहीं किया जाना चाहिए, चाहे भाषा की कल्पना क्यों न हो? (इसके अलावा, एक और नोट: यहां तक ​​कि अगर कीवर्ड मौजूद नहीं थे, जब तक निर्देश मौजूद थे, तब भी आप उन्हें गतिशील रूप से छोड़ने के तरीकों से एक्सेस कर सकते थे ... इसलिए जब तक आपका प्लेटफ़ॉर्म सी लाइब्रेरीज़ के साथ इंटरॉप नहीं करता, आप इनका उपयोग कर सकते हैं, C # के कीवर्ड हैं या नहीं।)
user541686

ओह, और एक और मुद्दा: भले ही यह पोर्टेबल न हो, उन्होंने कीवर्ड का दस्तावेजीकरण क्यों नहीं किया? बहुत कम से कम, यह आवश्यक है जब सी varargs के साथ संभोग किया जाए, तो कम से कम वे इसका उल्लेख कर सकते थे?
user541686

@ मेहरदाद: हं, यह दिलचस्प है। मुझे लगता है कि मैंने हमेशा यह माना है कि .NET स्रोत के BCL फ़ोल्डर में फाइलें BCL का हिस्सा हैं, वास्तव में ECMA मानकीकरण भाग पर कभी ध्यान नहीं देती हैं। यह बहुत आश्वस्त करने वाला है ... एक छोटी सी बात को छोड़कर: क्या यह सीएलआई युक्ति में (वैकल्पिक) सुविधा को शामिल करने के लिए थोड़ा भी व्यर्थ नहीं है, अगर कहीं भी इसका उपयोग करने का कोई दस्तावेज नहीं है? (यह समझ में आता है कि अगर TypedReferenceसिर्फ एक भाषा के लिए प्रलेखित किया गया था - कहो, प्रबंधित C ++ - लेकिन अगर कोई भाषा दस्तावेज़ नहीं है और इसलिए यदि कोई वास्तव में इसका उपयोग नहीं कर सकता है, तो भी सुविधा को परिभाषित करने में परेशान क्यों?)
user541686

@ मेहरदाद मुझे संदेह है कि प्राथमिक प्रेरणा इंटरोप ( जैसे [DllImport("...")] void Foo(__arglist); ) के लिए आंतरिक रूप से इस सुविधा की आवश्यकता थी और उन्होंने इसे सी # में अपने स्वयं के उपयोग के लिए लागू किया। सीएलआई का डिज़ाइन बहुत सारी भाषाओं (एनोटेशन) से प्रभावित है (कॉमन लैंग्वेज इन्फ्रास्ट्रक्चर एनोटेट स्टैंडर्ड इस तथ्य को प्रदर्शित करता है।) अनपेक्षित लोगों सहित यथासंभव अधिक से अधिक भाषाओं के लिए एक उपयुक्त रनटाइम होने के नाते, निश्चित रूप से एक डिज़ाइन लक्ष्य है (इसलिए नाम) और यह एक विशेषता है, उदाहरण के लिए, एक काल्पनिक प्रबंधित सी कार्यान्वयन शायद इससे लाभान्वित हो सकता है।
मेहरदाद अफश्री

@ मेहरदाद: आह ... हाँ, यह एक बहुत ठोस कारण है। धन्यवाद!
user541686

15

ठीक है, मैं कोई एरिक लिपर्ट नहीं हूं, इसलिए मैं सीधे Microsoft की प्रेरणाओं को नहीं बोल सकता, लेकिन अगर मैं एक अनुमान लगाता हूं, तो मैं कहूंगा कि TypedReferenceएट अल। अच्छी तरह से प्रलेखित नहीं हैं क्योंकि, स्पष्ट रूप से, आपको उनकी आवश्यकता नहीं है।

इन सुविधाओं के लिए आपके द्वारा बताए गए प्रत्येक उपयोग को उनके बिना पूरा किया जा सकता है, कुछ मामलों में एक प्रदर्शन दंड के रूप में। लेकिन C # (और .NET सामान्य रूप से) एक उच्च प्रदर्शन वाली भाषा नहीं है। (मुझे लगता है कि "जावा की तुलना में तेज़" प्रदर्शन लक्ष्य था।)

यह कहने के लिए नहीं है कि कुछ प्रदर्शनों पर विचार नहीं किया गया है। दरअसल, पॉइंटर्स, stackallocऔर कुछ अनुकूलित फ्रेमवर्क फ़ंक्शन के रूप में ऐसी विशेषताएं कुछ स्थितियों में प्रदर्शन को बढ़ावा देने के लिए बड़े पैमाने पर मौजूद हैं।

जेनरिक, जो कहेंगे कि मुझे सुरक्षा का प्राथमिक लाभ है, TypedReferenceबॉक्सिंग और अनबॉक्सिंग से बचने के साथ प्रदर्शन में भी सुधार होता है । वास्तव में, मैं सोच रहा था कि आप इसे क्यों पसंद करेंगे:

static void call(Action<int, TypedReference> action, TypedReference state){
    action(0, state);
}

इसके लिए:

static void call<T>(Action<int, T> action, T state){
    action(0, state);
}

व्यापार-नापसंद, जैसा कि मैं उन्हें देखता हूं, यह है कि पूर्व को कम जेआईटी (और, यह इस प्रकार है, कम मेमोरी) की आवश्यकता होती है, जबकि उत्तरार्द्ध अधिक परिचित है और, मुझे लगता है, थोड़ा तेजी से (सूचक डेरेफेरिंग से बचकर)।

मैं कॉल TypedReferenceऔर दोस्तों के कार्यान्वयन विवरण। आपने उनके लिए कुछ नीट उपयोगों की ओर इशारा किया है, और मुझे लगता है कि वे खोज के लायक हैं, लेकिन कार्यान्वयन विवरणों पर भरोसा करने का सामान्य तरीका लागू होता है - अगला संस्करण आपके कोड को तोड़ सकता है।


4
हुह ... "आपको उनकी आवश्यकता नहीं है" - मुझे यह देखना चाहिए था। :-) यह सच है लेकिन यह भी सच नहीं है। आप "आवश्यकता" के रूप में क्या परिभाषित करते हैं? क्या विस्तार के तरीके वास्तव में "आवश्यक" हैं, उदाहरण के लिए? जेनरिक का उपयोग करने के आपके प्रश्न के बारे में call(): यह इसलिए है क्योंकि कोड हमेशा इतना सामंजस्यपूर्ण नहीं होता है - मैं अधिक उदाहरण के लिए अधिक का उल्लेख कर रहा था IAsyncResult.State, जहां जेनेरिक को शुरू करना केवल संभव नहीं होगा क्योंकि अचानक यह सभी के लिए जेनरिक का परिचय देगा। हर वर्ग / विधि शामिल। उत्तर के लिए +1, हालांकि ... विशेष रूप से "जावा की तुलना में तेज़" भाग को इंगित करने के लिए। :]
user541686

1
ओह, और एक अन्य बिंदु: TypedReferenceशायद कभी भी जल्द ही ब्रेकिंग परिवर्तन से गुजरना नहीं होगा, यह देखते हुए कि FieldInfo.SetValueDirect , जो सार्वजनिक है और शायद कुछ डेवलपर्स द्वारा उपयोग किया जाता है, इस पर निर्भर करता है। :)
यूजर ५४१६ --६

आह, लेकिन आप करते जरूरत विस्तार के तरीकों, समर्थन LINQ करने के लिए। वैसे भी, मैं वास्तव में एक अच्छे-से-ज़रूरत / अंतर के बारे में बात नहीं कर रहा हूँ। मैं TypedReferenceउन दोनों में से किसी को भी फोन नहीं करूंगा । (अत्याचारी वाक्यविन्यास और समग्र अनिच्छा, इसे मेरे मन में, अच्छी-से-अच्छी श्रेणी से अयोग्य घोषित कर देती है।) मैं कहूंगा कि जब आप वास्तव में यहां और वहां कुछ माइक्रोसेकंड ट्रिम करने की आवश्यकता है, तो यह सिर्फ एक अच्छी बात है। उस ने कहा, मैं अपने स्वयं के कोड में कुछ स्थानों के बारे में सोच रहा हूं जो मैं अभी देखने जा रहा हूं, यह देखने के लिए कि क्या मैं आपके द्वारा बताई गई तकनीकों का उपयोग करके उन्हें अनुकूलित कर सकता हूं।
पी डैडी

1
@ मिरहाद: मैं एक बाइनरी ऑब्जेक्ट धारावाहिक / deserializer पर उस समय इंटरप्रोसेस / इंटरहोस्ट संचार (टीसीपी और पाइप) के लिए काम कर रहा था। मेरा लक्ष्य इसे जितना संभव हो उतना छोटा (तार के ऊपर भेजे गए बाइट्स के संदर्भ में) और उपवास (संभव के रूप में क्रमबद्ध और डीसर्विलाइज़िंग के रूप में) के रूप में संभव के रूप में करना था। मैंने सोचा कि मैं कुछ मुक्केबाजी और साथ unboxing न करना चाहें TypedReference, लेकिन IIRC, केवल जगह मैं मुक्केबाजी से बचने के लिए कर रहा था कहीं पुरातन के एकल आयामी सरणी के तत्वों के साथ किया गया था। यहां थोड़ी सी गति का लाभ पूरी परियोजना में जोड़ा गया जटिलता के लायक नहीं था, इसलिए मैंने इसे निकाल लिया।
पी डैडी

1
यह देखते हुए delegate void ActByRef<T1,T2>(ref T1 p1, ref T2 p2);प्रकार का एक संग्रह Tके लिए एक विधि प्रदान कर सकता है ActOnItem<TParam>(int index, ActByRef<T,TParam> proc, ref TParam param), लेकिन घबराना प्रत्येक मान प्रकार के लिए विधि का एक अलग संस्करण बनाने के लिए होता है TParam। टाइप किए गए संदर्भ का उपयोग करने से विधि का एक JITted संस्करण सभी पैरामीटर प्रकारों के साथ काम करने की अनुमति देगा।
18

4

मैं यह पता नहीं लगा सकता कि इस प्रश्न का शीर्षक व्यंग्यात्मक है या नहीं: यह लंबे समय से स्थापित है कि TypedReference'सही' प्रबंधित बिंदुओं की धीमी, फूली हुई, बदसूरत चचेरी बहन है, बाद में जिसे हम C ++ / CLI के साथ प्राप्त करते हैं interior_ptr<T>, या C # में भी पारंपरिक उप-संदर्भ ( ref/ out) पैरामीटर । वास्तव में, हर बार मूल सीएलआर सरणी को फिर से अनुक्रमित करने के लिए पूर्णांक का उपयोग करके आधारभूत प्रदर्शन तक भी पहुंचना बहुत कठिन है ।TypedReference

दुखद विवरण यहाँ हैं , लेकिन शुक्र है, इस मामले में से कोई भी अब ...

इस सवाल को अब नए रेफ लोकल द्वारा रिफंड किया गया है और C # 7 में रिफ रिटर्न फीचर्स हैं

ये नई भाषा सुविधाएँ C # को घोषित, साझा करने, और सावधानीपूर्वक पूर्वनिर्धारित परिस्थितियों में- सही CLR संदर्भ प्रकार प्रबंधित करने के लिए सी # में प्रमुख, प्रथम श्रेणी का समर्थन प्रदान करती हैं ।

उपयोग प्रतिबंधों के लिए पहले की आवश्यकता के मुकाबले कोई सख्त नहीं है TypedReference(और प्रदर्शन सचमुच सबसे खराब से सबसे अच्छी तरह से कूद रहा है), इसलिए मुझे C # के लिए कोई शेष बोधगम्य उपयोग मामला नहीं दिखता है TypedReference। उदाहरण के लिए, पहले ढेर TypedReferenceमें बने रहने का कोई तरीका नहीं था GC, इसलिए अब बेहतर प्रबंधित पॉइंटर्स के बारे में सही होना एक दूर की कौड़ी नहीं है।

और जाहिर है, TypedReferenceकम से कम-के __makerefरूप में पूरी तरह से पदावनति के निधन के रूप में अच्छी तरह से रद्दी पर फेंक देते हैं ।

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