সি # 'হল' অপারেটর পারফরম্যান্স


103

আমার একটি প্রোগ্রাম রয়েছে যার দ্রুত পারফরম্যান্স প্রয়োজন। এর একটি অভ্যন্তরীণ লুপের মধ্যে, একটি নির্দিষ্ট ইন্টারফেস থেকে এটি উত্তরাধিকার সূত্রে প্রাপ্ত কিনা তা দেখতে আমার কোনও ধরণের পরীক্ষা করতে হবে।

এটি করার একটি উপায় হ'ল সিএলআর অন্তর্নির্মিত টাইপ-চেকিং কার্যকারিতা সহ। সম্ভবত 'হ'ল মূলশব্দটি হ'ল সেখানে সবচেয়ে মার্জিত পদ্ধতি:

if (obj is ISpecialType)

অন্য পদ্ধতির ভিত্তিটি হবে ক্লাসটি আমার নিজস্ব ভার্চুয়াল গেটটাইপ () ফাংশন দেওয়া যা একটি প্রাক-সংজ্ঞায়িত এনাম মান প্রদান করে (আমার ক্ষেত্রে, আসলে আমার কেবল একটি বুল প্রয়োজন)। এই পদ্ধতিটি দ্রুত হবে, তবে মার্জিত কম হবে।

আমি শুনেছি 'আইজ' কীওয়ার্ডের জন্য বিশেষত একটি আইএল নির্দেশনা রয়েছে, তবে এর অর্থ এই নয় যে দেশীয় সমাবেশে অনুবাদ হওয়ার পরে এটি দ্রুত কার্যকর হয়। 'পদ্ধতি' বনাম অন্য পদ্ধতির পারফরম্যান্সের জন্য কেউ কি কিছুটা অন্তর্দৃষ্টি ভাগ করতে পারে?

আপডেট: সমস্ত অবহিত উত্তরের জন্য ধন্যবাদ! উত্তরের মধ্যে কয়েকটি সহায়ক পয়েন্ট ছড়িয়ে পড়েছে বলে মনে হচ্ছে: অ্যান্ড্রু'র বিষয়টি 'এর' সম্পর্কে স্বয়ংক্রিয়ভাবে একটি castালাই সম্পাদন করা অত্যাবশ্যক, তবে বাইনারি ওয়ারিয়ার এবং আয়ানের সংগৃহীত পারফরম্যান্সের ডেটাও অত্যন্ত কার্যকর। এই সমস্ত তথ্য অন্তর্ভুক্ত করার জন্য কোনও একটি উত্তর সম্পাদনা করা হলে এটি দুর্দান্ত হবে ।


4
বিটিডাব্লু, সিএলআর আপনাকে আপনার নিজস্ব টাইপ গেটটাইপ () ফাংশন তৈরি করার সম্ভাবনা দেয় না, কারণ এটি একটি প্রধান সিএলআর বিধি ভাঙে - সত্যিকারের ধরণ
২:26

4
তবুও, "সত্যিকারের টাইপস" বিধি দ্বারা আপনি কী বোঝাতে চাইছেন তা আমি পুরোপুরি নিশ্চিত নই, তবে আমি বুঝতে পারি যে সিএলআর-এর একটি বিল্ট-ইন টাইপ গেটটাইপ () ফাংশন রয়েছে। যদি আমি এই পদ্ধতিটি ব্যবহার করি তবে এটি অন্য নামের ফাংশন সহ কিছু এনাম ফেরত আসবে, সুতরাং কোনও নাম / প্রতীক বিরোধ নেই।
যুবজব

4
আমি মনে করি আবাতিশ্চেভ বলতে "প্রকারের সুরক্ষা" বোঝানো হয়েছিল। কোনও টাইপকে নিজের সম্পর্কে মিথ্যা বলা থেকে বাঁচাতে এবং তাই সুরক্ষা সংরক্ষণের জন্য গেটটাইপ () অ-ভার্চুয়াল।
অ্যান্ড্রু হারে

4
আপনি কি প্রাক-আনয়ন এবং প্রকারের সম্মতিটিকে ক্যাশে করার বিষয়টি বিবেচনা করেছেন যাতে আপনাকে এটি লুপের মধ্যে না করতে হয়? প্রতিটি পারফেক্ট প্রশ্নটি সর্বদা বৃহত্তরভাবে +1 করা মনে হয় তবে এটি আমার কাছে সি # এর দুর্বল বোঝার মতো বলে মনে হচ্ছে। আসলে কি খুব ধীর? কীভাবে? আপনি কি চেষ্টা করেছেন? অবশ্যই উত্তরগুলিতে আপনার মন্তব্যগুলি খুব একটা দেওয়া হয়নি ...
গুডডর

উত্তর:


115

ব্যবহারটি isপারফরম্যান্সের ক্ষতি করতে পারে যদি আপনি একবার এই টাইপটি পরীক্ষা করেন তবে আপনি সেই ধরণের কাছে কাস্ট করেন। isআপনি যে ধরণের পরীক্ষণ করছেন তা আসলে বস্তুটিকে কাস্ট করে যাতে কোনও পরবর্তী কাস্টিং অপ্রয়োজনীয় হয়।

আপনি যদি যাইহোক কাস্ট করতে চলেছেন তবে এখানে একটি আরও ভাল উপায়:

ISpecialType t = obj as ISpecialType;

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

4
ধন্যবাদ তবে যদি আমি শর্তসাপেক্ষে ব্যর্থ হয় তবে অবজেক্টটি castালতে যাচ্ছি না, পরিবর্তে টাইপটি পরীক্ষা করার জন্য আমি কি ভার্চুয়াল ফাংশনটি ব্যবহার করে ভাল করব?
যুবজুব

4
@ যুবজব: না। একটি ব্যর্থতা asমূলত is(যেমন, টাইপ চেক) একই ক্রিয়াকলাপ সম্পাদন করে । শুধু পার্থক্য এটি তারপর ফেরৎ nullপরিবর্তে false
কনরাড রুডল্ফ

74

আমি সাথে আছি ইয়ান , আপনি সম্ভবত না এই কাজ করতে চান।

যাইহোক, ঠিক তাই আপনি জানেন, উভয় মধ্যে 10,000,000 এর পুনরাবৃত্তির মধ্যে খুব কম পার্থক্য রয়েছে

  • এনাম চেক 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 মিলি সেকেন্ডে আসে।

এনবি আমি isচেকটি এখনও পছন্দ করব , পার্থক্যটি যত্নের জন্য খুব কম


35
অনুমান করার পরিবর্তে কার্য সম্পাদন পরীক্ষার জন্য +1।
জন টেকাব্যারি


4
আমি বোর্ডে এটি গ্রহণ করব, তবে এই উদাহরণে আমি মনে করি না এটির ফলাফলের উপর প্রভাব ফেলবে। ধন্যবাদ :)
বাইনারি ওয়ারিয়র

11
@ বাইনারি ওয়ারিয়ার- আপনার নতুন ক্লাসের অপারেটর বরাদ্দগুলি 'ইজ ' অপারেশনগুলিতে কোনও পারফরম্যান্সের পার্থক্যকে পুরোপুরি ছাপিয়ে যাচ্ছে। দুটি পৃথক প্রাক বরাদ্দ দৃষ্টান্ত পুনরায় ব্যবহার করে আপনি কেন সেই নতুন ক্রিয়াকলাপগুলি সরান না এবং তারপরে কোডটি পুনরায় চালনা করুন এবং আপনার ফলাফল পোস্ট করুন।

4
@ এমসিএমিল্যাব: আমি গ্যারান্টি দিচ্ছি আপনি যা কিছু করছেন তা আপনার isঅপারেটরের ফলে যে কোনও পারফরম্যান্স ক্ষয় হচ্ছে তার চেয়ে অনেক বড় আকারের বাধা আপনার কাছে রয়েছে এবং isঅপারেটরের চারপাশে ডিজাইনিং এবং কোডিংয়ের কথা শুনে এক ভাগ্যের জন্য ব্যয় হবে কোডের মান এবং শেষ পর্যন্ত স্ব-পরাজিত কর্মক্ষমতা অনুযায়ীও হবে। এই উদাহরণস্বরূপ আমি আমার বিবৃতি দ্বারা দাঁড়ানো। ' রান ' অপারেটর কখনই আপনার রানটাইম পারফরম্যান্সে সমস্যা হতে পারে না
বাইনারি ওয়ারিয়ার

23

ঠিক আছে তাই আমি কারও সাথে এই সম্পর্কে চ্যাট করছি এবং এটি আরও পরীক্ষা করার সিদ্ধান্ত নিয়েছি। আমি যতদূর বলতে পারি, টাইপ তথ্য সংরক্ষণের জন্য আপনার নিজের সদস্য বা ফাংশনটি পরীক্ষা করার সাথে তুলনা করে উভয়ের পারফরম্যান্স asএবং isখুব ভাল।

আমি ব্যবহার করেছি Stopwatch, যা আমি সবেমাত্র শিখেছি এটি সবচেয়ে নির্ভরযোগ্য পদ্ধতির নাও হতে পারে, তাই আমি চেষ্টাও করেছি UtcNow। পরে, আমি প্রসেসরের সময় পদ্ধতিরও চেষ্টা করেছিলাম যা UtcNowঅপ্রত্যাশিত তৈরি সময়গুলি সহ অনুরূপ বলে মনে হয় । আমি বেস ক্লাসটি কোনও ভার্চুয়াল দিয়ে অ-বিমূর্ত করার চেষ্টা করেছি তবে এটির কোনও উল্লেখযোগ্য প্রভাব আছে বলে মনে হয় না।

আমি এটি 16 গিগাবাইট র‍্যাম সহ কোয়াড কিউ 6600 এ চালিত করেছি। এমনকি 50 মিলিল পুনরাবৃত্তির পরেও সংখ্যাগুলি প্রায় +/- 50 বা এতটা মিলিসেকের কাছাকাছি চলে আসে যাতে আমি সামান্যতম পার্থক্যের মধ্যে খুব বেশি পড়তে পারি না।

এটি দেখতে আকর্ষণীয় ছিল যে x64 দ্রুত তৈরি হয়েছে তবে এক্স 86 এর চেয়ে ধীর হিসাবে চালিত হয়েছে

x64 রিলিজ মোড:
স্টপওয়াচ:
যেমন: 561ms
is:
বেস সম্পত্তি: 539ms
বেস ক্ষেত্র: 555ms
বেস আরও ক্ষেত্র: 552ms
ভার্চুয়াল getEnumType () পরীক্ষা: 556ms
ভার্চুয়াল আইএসবি () পরীক্ষা: 588ms
তৈরির সময়: 10416ms

উত্কনো:
যেমন: 499 মিমি
: 532ms
বেস সম্পত্তি: 479ms
বেস ক্ষেত্র: 502ms
বেস আরও ক্ষেত্র: 491ms
ভার্চুয়াল গেটইনামটাইপ (): 502ms
ভার্চুয়াল বুল ইসবি (): 522ms
তৈরির সময়: 285 মিমি (এই সংখ্যাটি উতকনোর সাথে অবিশ্বাস্য বলে মনে হচ্ছে also এছাড়াও আমি 109ms পাই এবং 806ms।)

x86 রিলিজ মোড:
স্টপওয়াচ:
যেমন: 391ms
হল: 423ms
বেস সম্পত্তি: 369ms
বেস ক্ষেত্র: 321ms
বেস আরও ক্ষেত্র: 339ms
ভার্চুয়াল getEnumType () পরীক্ষা: 361ms
ভার্চুয়াল ইসবি () পরীক্ষা: 365ms
তৈরির সময়: 14106ms

উত্কনো:
যেমন: 348 মিমি
: 375ms
বেস সম্পত্তি: 329ms
বেস ক্ষেত্র: 286ms
বেস আরও ক্ষেত্র: 309ms
ভার্চুয়াল getEnumType (): 321ms
ভার্চুয়াল বুল ইসবি (): 332 মিমি
তৈরির সময়: 544ms (এই সংখ্যাটি অবনক দিয়ে অবিশ্বাস্য বলে মনে হচ্ছে))

এখানে বেশিরভাগ কোড রয়েছে:

    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 সকাল-অপেশাদার শেক্সপিয়র ...) হওয়া বা না হওয়া: এই প্রশ্নটি: 'কোডটিতে নোবেলকে ভোগ করতে হবে কিনা বিমূর্ত ঘাঁটির গণনা এবং বৈশিষ্ট্য, বা কোনও মধ্যস্থতার অফার গ্রহণ করা ভাষাবিদ এবং এর নির্দেশনাটি চালিয়ে তাদের বিশ্বাস করবেন? অনুমান করা: অবাক করা; আর না; এবং এটি নির্ধারণ করার একটি সময় দ্বারা আমরা মাথা ব্যাথা এবং সময়সীমাবদ্ধ কোডারদের উত্তরাধিকারী এমন হাজার অবচেতন আশ্চর্যতা শেষ করি। 'ইশারায় ধর্মাবলম্বী হ'ল এটি বন্ধ T মরতে, না, ঘুমোতে; হ্যাঁ আমি ঘুমাবো, স্বপ্ন দেখার প্রবণতা হ'ল এবং ক্লাসের সর্বাধিক বেস থেকে উদ্ভূত হতে পারে।
জ্যারেড থার্স্ক

আমরা কি এ থেকে এই সিদ্ধান্তে পৌঁছাতে পারি যে কোনও সম্পত্তি অ্যাক্সেস x64 এর পরে দ্রুত হয় তারপরে কোনও ক্ষেত্র অ্যাক্সেস করা !!! কারণ এটি আমার জন্য অবাক হওয়ার নরক যে এটি কীভাবে হতে পারে?
দিদিয়ার এ

4
আমি এই সিদ্ধান্তে পৌঁছাতে পারব না, কারণ: "এমনকি 50 মিলিল পুনরাবৃত্তির পরেও সংখ্যাগুলি প্রায় +/- 50 বা তাই মিলিসেকের কাছাকাছি চলে আসে তাই আমি ছোটখাটো পার্থক্যগুলিতে খুব বেশি পড়তে পারি না।"
জ্যারেড থারস্ক

16

অ্যান্ড্রু ঠিক আছে। কোড বিশ্লেষণের সাথে বাস্তবে এটি ভিজ্যুয়াল স্টুডিওর দ্বারা একটি অপ্রয়োজনীয় castালাই হিসাবে প্রতিবেদন করা হয়।

একটি ধারণা (আপনি কী করছেন তা না জেনে অন্ধকারে খানিকটা গুলি) তবে আমাকে সর্বদা এই জাতীয় পরীক্ষা করা এড়াতে পরামর্শ দেওয়া হয়েছে এবং এর পরিবর্তে অন্য একটি ক্লাস করা উচিত। সুতরাং ধরণের উপর নির্ভর করে কিছু চেক করা এবং বিভিন্ন ক্রিয়া না করে শ্রেণিটিকে কীভাবে নিজে প্রক্রিয়া করা যায় তা নিশ্চিত করুন ...

যেমন ওবজ আইএসপেশাল টাইপ বা আইটি টাইপ হতে পারে;

তাদের উভয়ের একটি ডোস্টাফ () পদ্ধতি সংজ্ঞায়িত করা হয়েছে। আইটি টাইপের জন্য এটি কেবল কাস্টম স্টাফ ফিরিয়ে দিতে বা করতে পারে, অন্যদিকে আইএসপেশিয়াল টাইপ অন্যান্য জিনিসগুলি করতে পারে।

এরপরে এটি সম্পূর্ণরূপে কোনও ingালাই সরিয়ে দেয়, কোডটিকে আরও পরিষ্কার এবং বজায় রাখা সহজ করে তোলে এবং ক্লাসটি নিজের কাজগুলি কীভাবে করতে হয় তা জানে।


হ্যাঁ, যেহেতু আমি যা করতে যাচ্ছি তার সব ধরণের পরীক্ষাগুলি যদি এটির একটি নির্দিষ্ট ইন্টারফেস পদ্ধতি কল করে, আমি কেবল সেই ইন্টারফেস পদ্ধতিটি বেস শ্রেণিতে স্থানান্তর করতে পারতাম এবং এটি ডিফল্টরূপে কিছুই করতে পারি না। এটি পরীক্ষার ধরণের জন্য ভার্চুয়াল ফাংশন তৈরির চেয়ে আরও মার্জিত হতে পারে।
যুবজুব

আমি আবাতিশ্চভের মন্তব্যের পরে বাইনারি ওয়ারিয়ারের সাথে একই রকম পরীক্ষা দিয়েছি এবং 10,000,000 এর পরিবর্তনের চেয়ে 60 মাইলের পার্থক্য পেয়েছি।
ইয়ান

4
বাহ, সাহায্যের জন্য ধন্যবাদ। আমি মনে করি আমি আপাতত টাইপ চেকিং অপারেটরগুলি ব্যবহার করতে আটকে থাকব, যদি না শ্রেণিবদ্ধ কাঠামোর পুনর্গঠন করার জন্য এটি গ্রহণযোগ্য বলে মনে হয়। অ্যান্ড্রু প্রস্তাবিত হিসাবে আমি 'হিসাবে' অপারেটরটি ব্যবহার করব যেহেতু আমি অপ্রয়োজনীয়ভাবে কাস্ট করতে চাই না।
যুবজুব

15

টাইপ তুলনা দুটি সম্ভাবনার উপর আমি একটি পারফরম্যান্স তুলনা করেছি

  1. myobject.GetType () == টাইপফ (মাই ক্লাস)
  2. মায়োবজেক্টটি মাইক্লাস

ফলাফলটি হল: "is" ব্যবহার করা প্রায় 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চেক সঞ্চালন করেন এবং তারপরে কাস্ট বৈধ ছিল তবে সি # 7.0 এ আমরা অতিরিক্ত কাস্ট এড়াতে ডাইনী প্যাটার্ন ম্যাচটি চেক করতে পারি:

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

আরও যদি আপনার একাধিক প্রকারের সি # 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 # প্যাটার্ন ম্যাচিং সম্বন্ধে আরও পড়তে পারেন এখানে


4
একটি বৈধ সমাধান, অবশ্যই, তবে এই সি # প্যাটার্ন-মিলের বৈশিষ্ট্যটি আমাকে দুঃখ দেয়, যখন এটি "বৈশিষ্ট্য-enর্ষা" কোডটিকে উত্সাহ দেয়। অবশ্যই আমাদের যুক্তিগুলির encapsulation জন্য প্রয়াস করা উচিত যেখানে কেবল উদ্ভূত বস্তুগুলি তাদের নিজের ক্ষেত্রটি গণনা করতে "জানেন", এবং তারপরে তারা কেবল মানটি ফেরত দেয়?
দিনব

4
কোনও ফ্রেমওয়ার্ক, প্ল্যাটফর্ম ইত্যাদির নতুন সংস্করণগুলিতে প্রযোজ্য উত্তরগুলির জন্য এসওকে ফিল্টার বোতামের প্রয়োজন (প্রশ্নে) এই উত্তরটি সি # for এর জন্য সঠিক উত্তরটির ভিত্তি গঠন করে
নিক ওয়েস্টগেট

4
আপনি নিয়ন্ত্রণ করেন না এমন ধরণের / শ্রেণি / ইন্টারফেসের সাথে কাজ করার সময় @ ডিবি ওওপি আদর্শগুলি উইন্ডো থেকে ছিটকে যায়। এই ফাংশনটি এমন কোনও ফাংশনের ফলাফলটি পরিচালনা করার জন্যও কার্যকর যা পুরোপুরি বিভিন্ন ধরণের একের একাধিক মানকে ফিরিয়ে দিতে পারে (কারণ সি # এখনও ইউনিয়ন-প্রকারকে সমর্থন করে না - আপনি লাইব্রেরিগুলি ব্যবহার করতে পারেন OneOf<T...>তবে তাদের বড় অভাব রয়েছে) ।
দাই

5

যদি কেউ ভাবছেন, আমি ইউনিটি ইঞ্জিন 2017.1 তে স্ক্রিপ্টিং রানটাইম সংস্করণ দিয়ে পরীক্ষা করেছি made নেট 4.6 (অভিজ্ঞ) i5-4200U সিপিইউ সহ একটি নোটবুকে। ফলাফল:

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-compistance-is-vs-enum-vs-virtual-call.html


নিবন্ধ লিঙ্ক মারা গেছে।
জেমস উইলকিন্স

@ জামার লিঙ্কটি পুনরুদ্ধার করা হয়েছে।
গ্রু

ভাল জিনিস - তবে আমি আপনাকে হ্রাস করতে পারি না (আসলে আমি যাইহোক যাইহোক উন্নতি করেছি); আপনি যদি ভাবছেন। :)
জেমস উইলকিন্স

-3

আমাকে সর্বদা এইভাবে চেক এড়াতে পরামর্শ দেওয়া হয়েছে এবং এর পরিবর্তে অন্য একটি ক্লাস করা উচিত। সুতরাং ধরণের উপর নির্ভর করে কিছু চেক করা এবং বিভিন্ন ক্রিয়া না করে শ্রেণিটিকে কীভাবে নিজে প্রক্রিয়া করা যায় তা নিশ্চিত করুন ...

যেমন ওবজ আইএসপেশাল টাইপ বা আইটি টাইপ হতে পারে;

তাদের উভয়ের একটি ডোস্টাফ () পদ্ধতি সংজ্ঞায়িত করা হয়েছে। আইটি টাইপের জন্য এটি কেবল কাস্টম স্টাফ ফিরিয়ে দিতে বা করতে পারে, অন্যদিকে আইএসপেশিয়াল টাইপ অন্যান্য জিনিসগুলি করতে পারে।

এরপরে এটি সম্পূর্ণরূপে কোনও ingালাই সরিয়ে দেয়, কোডটিকে আরও পরিষ্কার এবং বজায় রাখা সহজ করে তোলে এবং ক্লাসটি নিজের কাজগুলি কীভাবে করতে হয় তা জানে।


4
এটি প্রশ্নের উত্তর দেয় না। যাইহোক, ক্লাসগুলি প্রসঙ্গের অভাবের কারণে কীভাবে নিজেকে প্রক্রিয়াজাত করতে হয় তা সর্বদা জানেন না। কিছু ব্যতিক্রম / পদ্ধতিতে ত্রুটিগুলি পরিচালনা করার পর্যাপ্ত প্রসঙ্গ না হওয়া পর্যন্ত আমরা ব্যতিক্রমগুলি কল শৃঙ্খলায় যেতে অনুমতি দিলে আমরা ব্যতিক্রম হ্যান্ডলিংয়ে অনুরূপ যুক্তি প্রয়োগ করি।
ভখতাং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.