C # 'ऑपरेटर प्रदर्शन है


102

मेरे पास एक कार्यक्रम है जिसे तेज प्रदर्शन की आवश्यकता है। इसकी आंतरिक छोरों में से एक के भीतर, मुझे यह देखने के लिए एक ऑब्जेक्ट के प्रकार का परीक्षण करने की आवश्यकता है कि क्या यह एक निश्चित इंटरफ़ेस से विरासत में मिला है।

ऐसा करने का एक तरीका सीएलआर के अंतर्निहित प्रकार की जाँच कार्यक्षमता के साथ होगा। संभवत: सबसे सुंदर तरीका 'कीवर्ड' है:

if (obj is ISpecialType)

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

मैंने सुना है कि विशेष रूप से 'is' कीवर्ड के लिए एक IL निर्देश है, लेकिन इसका मतलब यह नहीं है कि मूल असेंबली में अनुवादित होने पर यह तेजी से निष्पादित होता है। क्या कोई अन्य विधि बनाम 'के प्रदर्शन में कुछ अंतर्दृष्टि साझा कर सकता है?

अद्यतन: सभी सूचित जवाब के लिए धन्यवाद! ऐसा लगता है कि उत्तर के बीच कुछ सहायक बिंदुओं को फैलाया गया है: एंड्रयू के बारे में 'का कहना है' स्वचालित रूप से एक कलाकार का प्रदर्शन आवश्यक है, लेकिन बाइनरी वॉरियर और इयान द्वारा एकत्र किया गया प्रदर्शन डेटा भी बेहद उपयोगी है। यह बहुत अच्छा होगा यदि किसी एक उत्तर को सभी सूचनाओं को शामिल करने के लिए संपादित किया जाए ।


2
btw, सीएलआर आपको अपना स्वयं का टाइप गेटाइप () फ़ंक्शन बनाने की संभावना नहीं देगा, क्योंकि यह मुख्य सीएलआर नियमों में से एक को तोड़ता है - सही प्रकार
abatishchev

1
ईआर, मुझे पूरी तरह से यकीन नहीं है कि आपके "सही प्रकार" नियम से क्या मतलब है, लेकिन मैं समझता हूं कि सीएलआर में एक अंतर्निहित टाइप गेट टाइप () फ़ंक्शन है। अगर मैं उस पद्धति का उपयोग कर रहा था, तो यह एक अलग नाम के एक फ़ंक्शन के साथ होगा, जो कुछ एनम लौटाएगा, इसलिए कोई भी नाम / प्रतीक संघर्ष नहीं होगा।
जुबूब

3
मुझे लगता है कि abatishchev का अर्थ "प्रकार की सुरक्षा" था। गेट टाइप () अपने बारे में झूठ बोलने से एक प्रकार को रोकने के लिए गैर-आभासी है और इसलिए प्रकार की सुरक्षा को संरक्षित करता है।
एंड्रयू हरे

2
क्या आपने प्री-फ़ेचिंग पर विचार किया है और प्रकार के अनुपालन को कैशिंग कर रहे हैं ताकि आपको इसे छोरों के भीतर न करना पड़े? लगता है हर सही सवाल हमेशा बड़े पैमाने पर है + 1'd लेकिन यह सिर्फ मेरे लिए ग # की गरीब समझ की तरह लगता है। क्या यह वास्तव में बहुत धीमा है? कैसे? आपने क्या प्रयास किया है? स्पष्ट रूप से जवाबों पर आपकी टिप्पणियों को बहुत अधिक नहीं दिया गया ...
गुस्सोर

जवाबों:


114

का उपयोग isकरता है, तो, प्रदर्शन चोट एक बार आप प्रकार की जांच कर सकते हैं, तो आप उस प्रकार की डाली। isवास्तव में आप जिस प्रकार की जाँच कर रहे हैं, उस वस्तु को किसी भी बाद की ढलाई के लिए निरर्थक बता देता है।

यदि आप वैसे भी कास्ट करने जा रहे हैं, तो यहां एक बेहतर तरीका है:

ISpecialType t = obj as ISpecialType;

if (t != null)
{
    // use t here
}

1
धन्यवाद। लेकिन अगर मैं सशर्त विफल होने पर ऑब्जेक्ट कास्ट करने नहीं जा रहा हूं, तो क्या मैं इसके बजाय टाइप का परीक्षण करने के लिए वर्चुअल फ़ंक्शन का उपयोग करना बेहतर होगा?
जुबूब

4
@ जुबजब: नहीं। एक असफलता asमूल रूप से is(जैसे, चेक प्रकार) के समान ऑपरेशन करती है । फर्क सिर्फ इतना है कि यह nullइसके बजाय लौटता है false
कोनराड रुडोल्फ

74

मैं साथ हूँ इयान , तो आप शायद नहीं ऐसा करना चाहते हैं।

हालाँकि, बस इतना पता है कि 10,000,000 पुनरावृत्तियों पर दोनों के बीच बहुत कम अंतर है

  • Enum check 700 मिलीसेकंड (लगभग) में आता है
  • आईएस जाँच 1000 मिलीसेकंड (लगभग) में होती है

मैं व्यक्तिगत रूप से इस समस्या को ठीक नहीं करूंगा, लेकिन अगर मुझे एक तरीका अपनाने के लिए मजबूर किया गया तो इसे आईएस जांच में बनाया जाएगा, प्रदर्शन अंतर कोडिंग ओवरहेड पर विचार करने के लायक नहीं है।

मेरा आधार और व्युत्पन्न वर्ग

class MyBaseClass
{
    public enum ClassTypeEnum { A, B }
    public ClassTypeEnum ClassType { get; protected set; }
}

class MyClassA : MyBaseClass
{
    public MyClassA()
    {
        ClassType = MyBaseClass.ClassTypeEnum.A;
    }
}
class MyClassB : MyBaseClass
{
    public MyClassB()
    {
        ClassType = MyBaseClass.ClassTypeEnum.B;
    }
}

जुबजब: जैसा कि परीक्षणों पर अधिक जानकारी का अनुरोध किया गया है।

मैंने दोनों परीक्षणों को एक कंसोल ऐप (एक डीबग बिल्ड) से चलाया, प्रत्येक परीक्षण निम्न जैसा दिखता है

static void IsTest()
{
    DateTime start = DateTime.Now;
    for (int i = 0; i < 10000000; i++)
    {
        MyBaseClass a;
        if (i % 2 == 0)
            a = new MyClassA();
        else
            a = new MyClassB();
        bool b = a is MyClassB;
    }
    DateTime end = DateTime.Now;
    Console.WriteLine("Is test {0} miliseconds", (end - start).TotalMilliseconds);
}

रिलीज में चल रहा है, मुझे इयान की तरह 60 - 70 एमएस का अंतर मिलता है।

इसके अलावा अद्यतन - 25 अक्टूबर 2012
कुछ वर्षों के बाद मैंने इस बारे में कुछ देखा, संकलक bool b = a is MyClassBरिलीज में चूक कर सकता है क्योंकि बी का उपयोग कहीं भी नहीं किया जाता है।

यह कोड। । ।

public static void IsTest()
{
    long total = 0;
    var a = new MyClassA();
    var b = new MyClassB();
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < 10000000; i++)
    {
        MyBaseClass baseRef;
        if (i % 2 == 0)
            baseRef = a;//new MyClassA();
        else
            baseRef = b;// new MyClassB();
        //bool bo = baseRef is MyClassB;
        bool bo = baseRef.ClassType == MyBaseClass.ClassTypeEnum.B;
        if (bo) total += 1;
    }
    sw.Stop();
    Console.WriteLine("Is test {0} miliseconds {1}", sw.ElapsedMilliseconds, total);
}

। । । लगातार isलगभग 57 मिलीसेकंड में आने वाले चेक को दिखाता है , और 29 मिली सेकेंड में आने वाली दुश्मनी की तुलना करता है।

NB मैं अभी भी isचेक पसंद करूंगा , अंतर बहुत कम है


35
+1 वास्तव में मानने के बजाय प्रदर्शन का परीक्षण करने के लिए।
जॉन टैकबरी 16


2
मैं इसे बोर्ड पर ले जाऊंगा, हालांकि इस उदाहरण में मुझे नहीं लगता कि यह परिणाम को प्रभावित करेगा। धन्यवाद :)
बाइनरी वॉरियर

11
@ बेसिनियर बैरियर- कक्षाओं का आपका नया ऑपरेटर आवंटन पूरी तरह से 'पर' परिचालन में किसी भी प्रदर्शन अंतर को पूरा करने जा रहा है। आप दो अलग-अलग पूर्व-आवंटित उदाहरणों का पुन: उपयोग करके उन नए ऑपरेशनों को क्यों नहीं हटाते हैं , और फिर कोड को फिर से चलाएं और अपने परिणाम पोस्ट करें।

1
@mcmillab: मैं कि जो कुछ भी आप कर रहे हैं गारंटी देगा, तो आप बाधाओं परिमाण किसी भी प्रदर्शन गिरावट से भी बड़ा के कई आदेश होगा isऑपरेटर आप खड़ी कर रहा है, और उस पर डिजाइन और चारों ओर कोडिंग के बारे में सुना isऑपरेटर में एक भाग्य खर्च होंगे कोड की गुणवत्ता और अंततः आत्म पराजित प्रदर्शन बुद्धिमान भी होगा। इस उदाहरण में मैं अपने कथन के साथ खड़ा हूं। Performance is ’ऑपरेटर आपके रनटाइम प्रदर्शन के साथ कभी समस्या नहीं बनने वाला है।
बाइनरी वॉरियर

23

ठीक है तो मैं किसी के साथ इस बारे में बात कर रहा था और इसे और अधिक परीक्षण करने का फैसला किया। जहां तक ​​मैं बता सकता हूं, टाइप जानकारी को संग्रहीत करने के लिए अपने स्वयं के सदस्य या फ़ंक्शन का परीक्षण करने की तुलना में , का प्रदर्शन asऔर isदोनों बहुत अच्छे हैं।

मैंने उपयोग किया Stopwatch, जो कि मैंने अभी सीखा कि यह सबसे विश्वसनीय तरीका नहीं हो सकता है, इसलिए मैंने भी कोशिश की UtcNow। बाद में, मैंने प्रोसेसर समय के दृष्टिकोण की भी कोशिश की, जो UtcNowअप्रत्याशित बनाने के समय के समान है । मैंने बेस क्लास को बिना किसी वर्चुअल के एब्सट्रैक्ट बनाने की भी कोशिश की, लेकिन इसका कोई खास असर नहीं हुआ।

मैंने 16GB रैम के साथ क्वाड Q6600 पर इसे चलाया। यहां तक ​​कि 50 मीटर पुनरावृत्तियों के साथ, संख्या अभी भी +/- 50 के आसपास उछाल देती है या इसलिए मिलीसेक इसलिए मैं मामूली अंतर में बहुत अधिक नहीं पढ़ूंगा।

यह देखना दिलचस्प था कि x64 तेजी से बनाया गया है लेकिन x86 की तुलना में धीमी / निष्पादित है

x64 रिलीज़ मोड:
स्टॉपवॉच: के
रूप में: 561ms
है: 597ms
बेस प्रॉपर्टी: 539ms
बेस फील्ड: 555ms
बेस RO फ़ील्ड: 552ms
वर्चुअल गेटइंथम टाइप () टेस्ट: 556ms
वर्चुअल IsB () टेस्ट: 588ms
टाइम बनाएँ: 10416ms

UtcNow:
As: 499ms
है: 532ms
बेस प्रॉपर्टी: 479ms
बेस फील्ड: 502ms
बेस आरओ फील्ड: 491ms
वर्चुअल गेटइनमाइप (): 502ms
वर्चुअल बूल IsB (): 5msms
क्रिएट टाइम: 285ms (यह नंबर UtcNow के साथ अविश्वसनीय लगता है। मुझे 109ms भी मिलता है।) और 806ms।)

x86 रिलीज़ मोड:
स्टॉपवॉच: के
रूप में: 391ms
है: 423ms
बेस प्रॉपर्टी: 369ms
बेस फील्ड: 321ms
बेस आरओ फील्ड: 339ms
वर्चुअल गेटइनमाइप () टेस्ट: 361ms
वर्चुअल IsB () टेस्ट: 365ms
टाइम: 14106ms

UtcNow:
As: 348ms
है: 375ms
बेस प्रॉपर्टी: 329ms
बेस फील्ड: 286ms
Base RO फील्ड: 309ms
वर्चुअल गेटएन्नटाइप (): 321ms
वर्चुअल बूल IsB (): 332ms
क्रिएट टाइम: 544ms (यह संख्या UtcNow के साथ अविश्वसनीय लगती है।)

यहाँ अधिकांश कोड है:

    static readonly int iterations = 50000000;
    void IsTest()
    {
        Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1;
        MyBaseClass[] bases = new MyBaseClass[iterations];
        bool[] results1 = new bool[iterations];

        Stopwatch createTime = new Stopwatch();
        createTime.Start();
        DateTime createStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            if (i % 2 == 0) bases[i] = new MyClassA();
            else bases[i] = new MyClassB();
        }
        DateTime createStop = DateTime.UtcNow;
        createTime.Stop();


        Stopwatch isTimer = new Stopwatch();
        isTimer.Start();
        DateTime isStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] =  bases[i] is MyClassB;
        }
        DateTime isStop = DateTime.UtcNow; 
        isTimer.Stop();
        CheckResults(ref  results1);

        Stopwatch asTimer = new Stopwatch();
        asTimer.Start();
        DateTime asStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i] as MyClassB != null;
        }
        DateTime asStop = DateTime.UtcNow; 
        asTimer.Stop();
        CheckResults(ref  results1);

        Stopwatch baseMemberTime = new Stopwatch();
        baseMemberTime.Start();
        DateTime baseStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].ClassType == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime baseStop = DateTime.UtcNow;
        baseMemberTime.Stop();
        CheckResults(ref  results1);

        Stopwatch baseFieldTime = new Stopwatch();
        baseFieldTime.Start();
        DateTime baseFieldStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime baseFieldStop = DateTime.UtcNow;
        baseFieldTime.Stop();
        CheckResults(ref  results1);


        Stopwatch baseROFieldTime = new Stopwatch();
        baseROFieldTime.Start();
        DateTime baseROFieldStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime baseROFieldStop = DateTime.UtcNow;
        baseROFieldTime.Stop();
        CheckResults(ref  results1);

        Stopwatch virtMethTime = new Stopwatch();
        virtMethTime.Start();
        DateTime virtStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].GetClassType() == MyBaseClass.ClassTypeEnum.B;
        }
        DateTime virtStop = DateTime.UtcNow;
        virtMethTime.Stop();
        CheckResults(ref  results1);

        Stopwatch virtMethBoolTime = new Stopwatch();
        virtMethBoolTime.Start();
        DateTime virtBoolStart = DateTime.UtcNow;
        for (int i = 0; i < iterations; i++)
        {
            results1[i] = bases[i].IsB();
        }
        DateTime virtBoolStop = DateTime.UtcNow;
        virtMethBoolTime.Stop();
        CheckResults(ref  results1);


        asdf.Text +=
        "Stopwatch: " + Environment.NewLine 
          +   "As:  " + asTimer.ElapsedMilliseconds + "ms" + Environment.NewLine
           +"Is:  " + isTimer.ElapsedMilliseconds + "ms" + Environment.NewLine
           + "Base property:  " + baseMemberTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base field:  " + baseFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base RO field:  " + baseROFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType() test:  " + virtMethTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual IsB() test:  " + virtMethBoolTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Create Time :  " + createTime.ElapsedMilliseconds + "ms" + Environment.NewLine + Environment.NewLine+"UtcNow: " + Environment.NewLine + "As:  " + (asStop - asStart).Milliseconds + "ms" + Environment.NewLine + "Is:  " + (isStop - isStart).Milliseconds + "ms" + Environment.NewLine + "Base property:  " + (baseStop - baseStart).Milliseconds + "ms" + Environment.NewLine + "Base field:  " + (baseFieldStop - baseFieldStart).Milliseconds + "ms" + Environment.NewLine + "Base RO field:  " + (baseROFieldStop - baseROFieldStart).Milliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType():  " + (virtStop - virtStart).Milliseconds + "ms" + Environment.NewLine + "Virtual bool IsB():  " + (virtBoolStop - virtBoolStart).Milliseconds + "ms" + Environment.NewLine + "Create Time :  " + (createStop-createStart).Milliseconds + "ms" + Environment.NewLine;
    }
}

abstract class MyBaseClass
{
    public enum ClassTypeEnum { A, B }
    public ClassTypeEnum ClassType { get; protected set; }
    public ClassTypeEnum ClassTypeField;
    public readonly ClassTypeEnum ClassTypeReadonlyField;
    public abstract ClassTypeEnum GetClassType();
    public abstract bool IsB();
    protected MyBaseClass(ClassTypeEnum kind)
    {
        ClassTypeReadonlyField = kind;
    }
}

class MyClassA : MyBaseClass
{
    public override bool IsB() { return false; }
    public override ClassTypeEnum GetClassType() { return ClassTypeEnum.A; }
    public MyClassA() : base(MyBaseClass.ClassTypeEnum.A)
    {
        ClassType = MyBaseClass.ClassTypeEnum.A;
        ClassTypeField = MyBaseClass.ClassTypeEnum.A;            
    }
}
class MyClassB : MyBaseClass
{
    public override bool IsB() { return true; }
    public override ClassTypeEnum GetClassType() { return ClassTypeEnum.B; }
    public MyClassB() : base(MyBaseClass.ClassTypeEnum.B)
    {
        ClassType = MyBaseClass.ClassTypeEnum.B;
        ClassTypeField = MyBaseClass.ClassTypeEnum.B;
    }
}

45
(कुछ बोनस 5 am-inspired Shakespeare ...) होना या न होना: यह सवाल है: क्या 'tis nobler कोड में पीड़ित को सार आधारों की गणना और संपत्ति, या एक मध्यस्थ के प्रस्तावों को लेने के लिए भाषाविद् और इसके निर्देश को लागू करके, उन पर भरोसा करें? अनुमान लगाने के लिए: आश्चर्य करने के लिए; अब और नहीं; और समय-समय पर विचार करने के लिए हम सिरदर्द को समाप्त करते हैं और हजार अवचेतन आश्चर्य करते हैं कि समयबद्ध कोडर के लिए उत्तराधिकारी हैं। 'तीस को बंद करना Devoutly इच्छा होने के लिए। मरने के लिए, नहीं, बल्कि सोने के लिए; हाँ, मैं सोता हूँ, सपने देखने के लिए और वर्ग के सबसे आधार से प्राप्त किया जा सकता है के रूप में सपना है।
जेरेड थिरस्क

क्या हम इससे यह निष्कर्ष निकाल सकते हैं कि एक संपत्ति तक पहुँच x64 पर तेजी से है फिर एक क्षेत्र तक पहुँचने !!! कारण है कि मेरे लिए एक आश्चर्य का नरक है कि यह कैसे हो सकता है?
डिडियर ए।

1
मैं इसका निष्कर्ष नहीं निकालूंगा, क्योंकि: "यहां तक ​​कि 50 मिलियन पुनरावृत्तियों के साथ, संख्या अभी भी +/- 50 या इतने मिलीसेकंड के आसपास उछलती है, इसलिए मैं मामूली अंतर में बहुत अधिक नहीं पढ़ूंगा।"
जेरेड थिरस्क

16

एंड्रयू सही है। वास्तव में कोड विश्लेषण के साथ यह विजुअल स्टूडियो द्वारा एक अनावश्यक कलाकार के रूप में रिपोर्ट किया जाता है।

एक विचार (यह जानने के बिना कि आप जो कर रहे हैं वह अंधेरे में एक शॉट है), लेकिन मुझे हमेशा इस तरह की जाँच से बचने की सलाह दी गई है, और इसके बजाय एक और वर्ग है। इसलिए कुछ जाँच करने और प्रकार के आधार पर अलग-अलग क्रियाएं करने के बजाय, कक्षा को स्वयं को संसाधित करने का तरीका जानें ...

उदाहरण के लिए ओब्ज ISpecialType या IType हो सकता है;

दोनों में एक DoStuff () विधि परिभाषित है। IType के लिए यह केवल कस्टम सामान वापस कर सकता है या कर सकता है, जबकि ISpecialType अन्य सामान कर सकता है।

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


हां, चूंकि मैं यह करने जा रहा हूं कि यदि टाइप टेस्ट सही है, तो यह एक निश्चित इंटरफ़ेस विधि है, मैं बस उस इंटरफ़ेस विधि को बेस क्लास में ले जा सकता हूं और इसमें डिफ़ॉल्ट रूप से कुछ भी नहीं है। परीक्षण प्रकार के लिए वर्चुअल फ़ंक्शन बनाने से अधिक सुरुचिपूर्ण हो सकता है।
जुबूब

मैंने बाइनरी वॉरियर के लिए abatishchev की टिप्पणियों के बाद एक समान परीक्षण किया और 10,000,000 पुनरावृत्तियों पर केवल 60ms का अंतर पाया।
इयान

1
वाह, मदद के लिए धन्यवाद। मुझे लगता है कि मैं तब तक के लिए टाइप चेकिंग ऑपरेटरों का उपयोग करूंगा, जब तक कि यह क्लास संरचना को पुनर्गठित करने के लिए उपयुक्त नहीं लगता। मैं 'के रूप में' ऑपरेटर एंड्रयू के रूप में सुझाव दिया है के बाद से मैं अनावश्यक रूप से कास्ट नहीं करना चाहता हूँ का उपयोग करेंगे।
जुबजब

15

मैंने तुलनात्मक तुलना की दो संभावनाओं पर एक प्रदर्शन समझौता किया

  1. myobject.GetType () == टाइपोफ़ (MyClass)
  2. myobject MyClass है

परिणाम है: "का उपयोग कर" लगभग 10x तेज है !!!

आउटपुट:

टाइप-तुलना के लिए समय: 00: 00: 00.456

ई-तुलना के लिए समय: 00: 00: 00.042

मेरा कोड:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConsoleApplication3
{
    class MyClass
    {
        double foo = 1.23;
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass myobj = new MyClass();
            int n = 10000000;

            Stopwatch sw = Stopwatch.StartNew();

            for (int i = 0; i < n; i++)
            {
                bool b = myobj.GetType() == typeof(MyClass);
            }

            sw.Stop();
            Console.WriteLine("Time for Type-Comparison: " + GetElapsedString(sw));

            sw = Stopwatch.StartNew();

            for (int i = 0; i < n; i++)
            {
                bool b = myobj is MyClass;
            }

            sw.Stop();
            Console.WriteLine("Time for Is-Comparison: " + GetElapsedString(sw));
        }

        public static string GetElapsedString(Stopwatch sw)
        {
            TimeSpan ts = sw.Elapsed;
            return String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
        }
    }
}

13

पॉइंट एंड्रयू हरे ने प्रदर्शन के बारे में बनाया जब आप isचेक प्रदर्शन करते हैं और फिर कास्ट मान्य होता है, लेकिन C # 7.0 में हम कर सकते हैं कि बाद में अतिरिक्त कलाकारों से बचने के लिए डायन पैटर्न मैच की जाँच करें:

if (obj is ISpecialType st)
{
   //st is in scope here and can be used
}

और अधिक अगर आपको कई प्रकारों के बीच जांच करने की आवश्यकता है C # 7.0 पैटर्न से मेल खाने वाले निर्माण अब आपको switchप्रकारों पर करने की अनुमति देते हैं :

public static double ComputeAreaModernSwitch(object shape)
{
    switch (shape)
    {
        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        case Rectangle r:
            return r.Height * r.Length;
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

आप यहाँ प्रलेखन में C # में पैटर्न मिलान के बारे में अधिक पढ़ सकते हैं ।


1
एक वैध समाधान, निश्चित रूप से, लेकिन यह सी # पैटर्न-मिलान सुविधा मुझे दुखी करती है, जब यह इस तरह "फीचर-ईर्ष्या" कोड को प्रोत्साहित करती है। निश्चित रूप से हमें तर्क के इनकैप्सुलेशन के लिए प्रयास करना चाहिए जहां केवल व्युत्पन्न वस्तुओं को "पता है" कि अपने स्वयं के क्षेत्र की गणना कैसे करें, और फिर वे सिर्फ मूल्य वापस करते हैं?
दिबा

2
SO को एक फ्रेमवर्क, प्लेटफॉर्म आदि के नए संस्करणों पर लागू होने वाले उत्तरों के लिए फ़िल्टर बटन (प्रश्न पर) की आवश्यकता होती है। यह उत्तर C # 7. के लिए सही एक का आधार बनाता है
निक वेस्टगेट

1
जब आप प्रकार / वर्ग / इंटरफेस के साथ काम कर रहे होते हैं तो @Dib OOP आदर्शों को खिड़की से बाहर फेंक दिया जाता है जिन्हें आप नियंत्रित नहीं करते हैं। यह दृष्टिकोण उस फ़ंक्शन के लिए भी उपयोगी है जब एक फ़ंक्शन के परिणाम को संभाल सकता है जो पूरी तरह से अलग-अलग प्रकारों के एक-के-कई मान वापस कर सकता है (क्योंकि C # अभी भी यूनियन-प्रकारों का समर्थन नहीं करता है - आप पुस्तकालयों का उपयोग कर सकते हैं, OneOf<T...>लेकिन उनकी बड़ी कमियां हैं) ।
दाई

4

यदि कोई सोच रहा है, तो मैंने i5-4200U CPU के साथ नोटबुक पर रनटाइम संस्करण .NET4.6 (एक्सपेरिमेंटल) स्क्रिप्टिंग के साथ, एकता इंजन 2017.1 में परीक्षण किए हैं। परिणाम:

Average Relative To Local Call LocalCall 117.33 1.00 is 241.67 2.06 Enum 139.33 1.19 VCall 294.33 2.51 GetType 276.00 2.35

पूरा लेख: http://www.ennoble-studios.com/tuts/unity-c-performance-comparison-is-vs-enum-vs-virtual-call.html


लेख लिंक मृत है।
जेम्स विल्किंस

@ नाम लिंक पुनर्जीवित।
ग्रू

अच्छा सामान - लेकिन मैंने आपको निराश नहीं किया (वास्तव में मैंने वैसे भी उत्थान किया); मामले में आप सोच रहे हैं। :)
जेम्स विल्किंस

-3

मुझे हमेशा इस तरह की जाँच से बचने की सलाह दी गई है, और इसके बजाय एक और वर्ग है। इसलिए कुछ जाँचें करने और प्रकार के आधार पर अलग-अलग क्रियाएं करने के बजाय, कक्षा को स्वयं को संसाधित करने का तरीका जानें ...

उदाहरण के लिए ओब्ज ISpecialType या IType हो सकता है;

दोनों में एक DoStuff () विधि परिभाषित है। IType के लिए यह केवल कस्टम सामान वापस कर सकता है या कर सकता है, जबकि ISpecialType अन्य सामान कर सकता है।

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


1
इस सवाल का जवाब नहीं है। वैसे भी, कक्षाएं हमेशा नहीं जान सकतीं कि संदर्भ की कमी के कारण खुद को कैसे संसाधित किया जाए। हम अपवाद हैंडलिंग पर समान तर्क लागू करते हैं जब हम अपवादों को कॉल श्रृंखला तक जाने की अनुमति देते हैं जब तक कि किसी विधि / फ़ंक्शन में त्रुटियों को संभालने के लिए पर्याप्त संदर्भ न हो।
वख्तंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.