سؤال

ما الفرق بين البنية و الطبقة .الشبكة ؟

هل كانت مفيدة؟

المحلول

في .صافي, هناك نوعان من أنواع ، أنواع المراجع و أنواع القيم.

البنيات هي أنواع القيم و الطبقات أنواع المراجع.

العامة الفرق هو أن نوع مرجع يعيش على كومة ، نوع القيمة حياة مضمنة ، وهذا هو ، أينما كان هو المتغير الخاص بك أو مجال محدد.

متغير يحتوي على نوع القيمة يحتوي على كامل نوع القيمة القيمة.بالنسبة البنية ، وهذا يعني أن المتغير يحتوي على كامل البنية جميع المجالات.

متغير يحتوي على نوع مرجع يحتوي على مؤشر أو المرجعية إلى مكان آخر في الذاكرة حيث القيمة الفعلية يقيم.

وهذا له فائدة واحدة ، لتبدأ:

  • أنواع القيم دائما يحتوي على قيمة
  • أنواع المراجع يمكن أن تحتوي على null-المرجعية ، مما يعني أنها لا تشير إلى أي شيء على الإطلاق في هذه اللحظة

داخليا ، نوع مرجعs يتم تنفيذها في المؤشرات ، مع العلم أن معرفة كيفية تعيين متغير يعمل ، وهناك غيرها من الأنماط السلوكية:

  • نسخ محتويات نوع القيمة متغير إلى متغير آخر ، نسخ محتويات في متغير جديد ، مما يجعل متميزتين.وبعبارة أخرى, بعد نسخ التغييرات لن تؤثر على الأخرى
  • نسخ محتويات نوع مرجع متغير إلى متغير آخر ، نسخ المرجعية ، مما يعني أن لديك الآن اثنين من إشارات إلى نفس في مكان آخر تخزين البيانات الفعلية.وبعبارة أخرى, بعد نسخ أو تغيير البيانات في مرجع واحد سوف تظهر أن يؤثر على الآخر, ولكن فقط لأن كنت حقا تبحث فقط على نفس البيانات في كل الأماكن

عندما تقوم بتعريف المتغيرات أو الحقول ، هنا كيف نوعين تختلف:

  • المتغير: نوع القيمة يعيش على المكدس ، نوع مرجع يعيش على المكدس كما مؤشر في مكان ما في كومة الذاكرة حيث الذاكرة الفعلية حياة (على الرغم من ملاحظة إريك Lipperts سلسلة المادة:المكدس هو تنفيذ التفاصيل.)
  • الصف/البنية الميدان: نوع القيمة يعيش تماما داخل النوع ، نوع مرجع يعيش داخل نوع مؤشر إلى مكان ما في كومة الذاكرة حيث الذاكرة الفعلية حياة.

نصائح أخرى

ملخص قصير من كل:

فصول فقط:

  • يمكن أن تدعم الميراث
  • هي المرجعية (المؤشر) أنواع
  • المرجعية يمكن أن تكون فارغة
  • الذاكرة العامة في مثيل جديد

البنيات فقط:

  • لا يمكن دعم الميراث
  • هي أنواع قيمة
  • يتم تمريرها حسب القيمة (مثل الأعداد الصحيحة)
  • لا يمكن أن يكون مرجع فارغة (إلا إذا Nullable يستخدم)
  • لم يكن لديك ذاكرة النفقات العامة في مثيل جديد - إلا إذا 'محاصر'

كل دروس و البنيات:

  • هي مركب أنواع البيانات التي تستخدم عادة تحتوي على عدد قليل من المتغيرات التي لها علاقة منطقية
  • يمكن أن تحتوي على أساليب الأحداث
  • يمكن أن تدعم واجهات

في .صافي البنية فئة الإعلانات التفريق بين المرجعية أنواع و أنواع قيمة.

عند تمرير الجولة نوع مرجع هناك واحد فقط المخزنة في الواقع.كافة التعليمات البرمجية التي يصل سبيل المثال هو الوصول إلى نفس واحدة.

عند تمرير الجولة نوع قيمة كل واحد نسخة.كل رمز هو نسخ.

هذا يمكن أن تظهر مع مثال:

struct MyStruct 
{
    string MyProperty { get; set; }
}

void ChangeMyStruct(MyStruct input) 
{ 
   input.MyProperty = "new value";
}

...

// Create value type
MyStruct testStruct = new MyStruct { MyProperty = "initial value" }; 

ChangeMyStruct(testStruct);

// Value of testStruct.MyProperty is still "initial value"
// - the method changed a new copy of the structure.

لفئة هذا سيكون مختلفا

class MyClass 
{
    string MyProperty { get; set; }
}

void ChangeMyClass(MyClass input) 
{ 
   input.MyProperty = "new value";
}

...

// Create reference type
MyClass testClass = new MyClass { MyProperty = "initial value" };

ChangeMyClass(testClass);

// Value of testClass.MyProperty is now "new value" 
// - the method changed the instance passed.

الطبقات يمكن أن يكون أي شيء - الإشارة يمكن أن نشير إلى null.

البنيات هي القيمة الفعلية - أنها يمكن أن تكون فارغة ولكن لم null.لهذا السبب البنيات دائما منشئ افتراضي مع أي معلمة - أنها بحاجة إلى 'ابتداء من القيمة.

من مايكروسوفت اختيار بين فئة البنية ...

وكقاعدة عامة من الإبهام, معظم أنواع في إطار فصول.ومع ذلك ، هناك بعض الحالات التي خصائص نوع القيمة جعلها أكثر ملاءمة للاستخدام البنيات.

النظر في البنية بدلا من فئة:

  • وفي حالات من هذا النوع صغيرة عادة قصيرة الأجل أو عادة جزءا لا يتجزأ في الكائنات الأخرى.

X تجنب البنية إلا إذا كان نوع كل التالية الخصائص:

  • ذلك منطقيا يمثل قيمة واحدة ، على غرار أنواع بدائية (int, double, الخ.).
  • وقد مثيل الحجم تحت 16 بايت.
  • هو غير قابل للتغيير. (لا يمكن تغيير)
  • فإنه لن يكون محاصر في كثير من الأحيان.

بالإضافة إلى جميع الفروق المبينة في إجابات أخرى:

  1. البنيات لا يمكن أن يكون صريح parameterless منشئ في حين أن فئة يمكن أن
  2. البنيات لا يمكن أن يكون destructors, بينما فئة يمكن أن
  3. البنيات لا يمكن أن ترث من آخر البنية أو فئة في حين أن فئة يمكن أن ترث من فئة أخرى.(كل البنيات و دروس يمكن أن تنفذ من واجهة.)

إذا كنت بعد فيديو شرح جميع الخلافات, يمكنك التحقق من جزء 29 - C# البرنامج التعليمي - الفرق بين الطبقات و البنيات في C#.

حالات الفصول المخزنة على الكومة المدارة.جميع المتغيرات التي تحتوي على' مثيل ببساطة إشارة إلى مثيل على كومة.تمرير كائن إلى الأسلوب النتائج في نسخة من المرجعية التي يتم تمريرها ، ليس هدف في حد ذاته.

هياكل (تقنيا أنواع قيمة) المخزنة أينما تستخدم اكثر من نوع بدائي.محتويات يجوز نسخ قبل وقت التشغيل في أي وقت ودون التذرع مخصصة نسخ-منشئ.تمرير قيمة من نوع إلى الأسلوب ينطوي على نسخ القيمة بأكملها مرة أخرى دون الاستناد إلى أي رمز للتخصيص.

الفرق هو أفضل من C++/CLI الأسماء:"المرجع فئة" هي الفئة كما هو موضح أولا "قيمة" الطبقة هي الطبقة كما هو موضح الثانية.الكلمات الرئيسية "الطبقة" و "البنية" التي استخدمت في C# هي مجرد شيء التي يجب أن يتعلمها.

الفرق بين البنيات و فصول:

  • البنيات هي نوع القيمة في حين الطبقات هي نوع مرجع.
  • البنيات يتم تخزينها في المكدس في حين الفصول المخزنة على كومة.
  • أنواع قيمة عقد قيمتها في الذاكرة حيث يتم الإعلان عنها ، ولكن نوع مرجع يحمل إشارة إلى كائن الذاكرة.
  • أنواع قيمة دمرت على الفور بعد نطاق فقدت حين نوع مرجع فقط متغير بعد تدمير نطاق المفقودة.على الكائن في وقت لاحق دمرت من قبل هواة جمع القمامة.
  • عند نسخ البنية في البنية ، نسخة جديدة من أن البنية يحصل على خلق تعديل واحد البنية لن تؤثر على قيمة غيرها من البنية.
  • عند نسخ فئة إلى فئة أخرى ، فقط نسخ مرجع متغير.
  • كل متغير إشارة تشير إلى نفس الكائن على كومة.تغيير متغير واحد يؤثر على الآخر مرجع متغير.
  • البنيات لا يمكن أن يكون destructors, ولكن الطبقات يمكن أن يكون المتلفات.
  • البنيات لا يمكن أن يكون صريحا parameterless المنشئات بينما فئة يمكن أن البنيات لا يدعم الميراث ، ولكن فئات.سواء دعم الميراث من واجهة.
  • البنيات مختومة نوع.

هيكل مقابل فئة

الهيكل هو نوع قيمة لذلك يتم تخزينها في المكدس ، لكن فئة هو نوع مرجع ويتم تخزينها على كومة.

هيكل لا يدعم الإرث و تعدد الأشكال, ولكن فئة يدعم كلا.

افتراضي جميع البنية أعضاء الجمهور ولكن أعضاء الفئة بشكل افتراضي خاص في الطبيعة.

كما أن هيكل هو نوع القيمة لا يمكننا تعيين null إلى البنية وجوه ، ولكن ذلك ليس هو الحال لفئة.

فقط لجعلها كاملة ، وهناك فرق آخر عند استخدام Equals الطريقة التي ورثت من جميع الطبقات و الهياكل.

دعونا نقول لدينا فئة هيكل:

class A{
  public int a, b;
}
struct B{
  public int a, b;
}

و في الأسلوب الرئيسي لدينا 4 الأجسام.

static void Main{
  A c1 = new A(), c2 = new A();
  c1.a = c1.b = c2.a = c2.b = 1;
  B s1 = new B(), s2 = new B();
  s1.a = s1.b = s2.a = s2.b = 1;
}

ثم:

s1.Equals(s2) // true
s1.Equals(c1) // false
c1.Equals(c2) // false
c1 == c2 // false

لذلك, والهياكل تناسب عددي-مثل الأشياء مثل نقاط (حفظ إحداثيات x وy).وفئات تناسب الآخرين.حتى لو 2 الناس لديهم نفس الاسم ، الطول ، الوزن..., أنها لا تزال 2 الناس.

إضافة إلى إجابات أخرى, هناك فرق جوهري أن الجدير بالذكر ، أن هو كيف يتم تخزينها في الذاكرة.هذا يمكن أن يكون لها تأثير كبير على أداء المصفوفات.البنيات هي أنواع قيمة ، لذلك هم تخزين قيمة في مجال الذاكرة انهم مشيرا إلى الطبقات هي أنواع المراجع ، حتى أنها إشارة فئة في مجال الذاكرة انهم مشيرا إلى أن القيمة الفعلية المخزنة في مكان آخر.

  • مع البنية ، يتم تخصيص الذاكرة ضمن تحتوي الطبقة لتخزين البيانات.
  • مع الفئة التي تحتوي على فئة فقط تحتوي على مؤشر إلى فئة جديدة في منطقة مختلفة من الذاكرة.

وهذا أيضا صحيح مع المصفوفات ، لذلك مجموعة من البنيات يبدو مثل هذا في الذاكرة

[struct][struct][struct][struct][struct][struct][struct][struct]

حيث مجموعة من الطبقات يبدو مثل هذا

[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]

القيم الفعلية كنت مهتما ليست في الواقع المخزنة في صفيف ، ولكن في أماكن أخرى في الذاكرة.

على الغالبية العظمى من تطبيقات هذا الفرق لا يهم حقا, ومع ذلك ، في عالية الأداء رمز هذا سوف يؤثر محلة البيانات داخل الذاكرة و يكون لها تأثير كبير على أداء وحدة المعالجة المركزية ذاكرة التخزين المؤقت.استخدام الطبقات عندما يمكن/ينبغي أن تستخدم البنيات نطاق واسع زيادة عدد ذاكرة التخزين المؤقت يخطئ على وحدة المعالجة المركزية.

أبطأ الشيء الحديثة وحدة المعالجة المركزية لا ليست أزمة الأرقام هي جلب البيانات من الذاكرة ، L1 cache ضرب عدة مرات أسرع من قراءة البيانات من ذاكرة الوصول العشوائي.

حسنا بالنسبة للمبتدئين ، struct يتم تمريرها حسب القيمة بدلا من الإشارة.البنيات جيدة نسبيا بسيطة هياكل البيانات ، في حين أن الطبقات لديها الكثير من المرونة من وجهة نظر معمارية عبر تعدد الأشكال و الميراث.

والبعض الآخر ربما يمكن أن تعطيك المزيد من التفاصيل لكن يمكنني استخدام البنيات عندما الهيكل الذي أنا ذاهب بسيط.

إلى جانب الفرق الأساسي الوصول محدد ، القليلة المذكورة أعلاه أود أن أضيف بعض الاختلافات الرئيسية بما في ذلك عدد قليل من المذكورة أعلاه مع نموذج التعليمات البرمجية مع الإخراج ، والتي سوف تعطي فكرة أكثر وضوحا من الإشارة والقيمة

البنيات:

  • هي أنواع قيمة و لا تتطلب تخصيص كومة الذاكرة المؤقتة.
  • تخصيص الذاكرة مختلفة و يتم تخزينها في المكدس
  • مفيدة صغيرة هياكل البيانات
  • تؤثر على الأداء ، عندما نعبر قيمة الأسلوب ، ونحن تمرير كامل هيكل البيانات وجميع يتم تمريرها إلى المكدس.
  • منشئ يعود ببساطة البنية القيمة نفسها (عادة في موقع مؤقت على المكدس) و هذه القيمة ثم نسخ عند الضرورة
  • المتغيرات لكل نسخ البيانات, و ليس من الممكن العمليات على واحد يؤثر على الآخر.
  • لا تدعم المحددة من قبل المستخدم الميراث ، ضمنا ترث من نوع كائن

الدرجة:

  • نوع مرجع القيمة
  • المخزنة في كومة
  • متجر إشارة إلى تخصيص حيوي كائن
  • المنشئات يتم استدعاء مع المشغل الجديد, ولكن هذا لا تخصيص الذاكرة في كومة الذاكرة المؤقتة
  • متغيرات متعددة قد يكون إشارة إلى نفس الكائن
  • فمن الممكن العمليات على متغير واحد أن تؤثر على الكائن المشار إليه قبل الأخرى متغيرة

نموذج التعليمات البرمجية

    static void Main(string[] args)
    {
        //Struct
        myStruct objStruct = new myStruct();
        objStruct.x = 10;
        Console.WriteLine("Initial value of Struct Object is: " + objStruct.x);
        Console.WriteLine();
        methodStruct(objStruct);
        Console.WriteLine();
        Console.WriteLine("After Method call value of Struct Object is: " + objStruct.x);
        Console.WriteLine();

        //Class
        myClass objClass = new myClass(10);
        Console.WriteLine("Initial value of Class Object is: " + objClass.x);
        Console.WriteLine();
        methodClass(objClass);
        Console.WriteLine();
        Console.WriteLine("After Method call value of Class Object is: " + objClass.x);
        Console.Read();
    }
    static void methodStruct(myStruct newStruct)
    {
        newStruct.x = 20;
        Console.WriteLine("Inside Struct Method");
        Console.WriteLine("Inside Method value of Struct Object is: " + newStruct.x);
    }
    static void methodClass(myClass newClass)
    {
        newClass.x = 20;
        Console.WriteLine("Inside Class Method");
        Console.WriteLine("Inside Method value of Class Object is: " + newClass.x);
    }
    public struct myStruct
    {
        public int x;
        public myStruct(int xCons)
        {
            this.x = xCons;
        }
    }
    public class myClass
    {
        public int x;
        public myClass(int xCons)
        {
            this.x = xCons;
        }
    }

الإخراج

القيمة الأولية من البنية وجوه:10

داخل البنية الطريقة داخل طريقة قيمة البنية وجوه:20

بعد استدعاء الأسلوب قيمة البنية وجوه:10

القيمة الأولية من فئة الكائن:10

داخل الطبقة الطريقة داخل طريقة قيمة كائن الفئة هو:20

بعد استدعاء الأسلوب قيمة كائن الفئة هو:20

هنا يمكنك أن ترى بوضوح الفرق بين دعوة القيمة دعوة المرجعية.

  1. الأحداث أعلن في فئة لها += و= الوصول آلي عن طريق قفل(هذا) لجعلها موضوع آمنة (ثابت الأحداث مقفل على typeof الصف).الأحداث أعلن في البنية لا += و= الوصول مؤمن تلقائيا.قفل(هذا) على البنية لن تعمل حيث يمكنك فقط قفل على نوع مرجع التعبير.

  2. إنشاء البنية سبيل المثال لا يسبب جمع القمامة (ما لم يكن منشئ بشكل مباشر أو غير مباشر يخلق نوع مرجع سبيل المثال) في حين خلق نوع مرجع سبيل المثال يمكن أن تتسبب في جمع القمامة.

  3. البنية دائما لديه المدمج في العام منشئ افتراضي.

    class DefaultConstructor
    {
        static void Eg()
        {
            Direct     yes = new   Direct(); // Always compiles OK
            InDirect maybe = new InDirect(); // Compiles if constructor exists and is accessible
            //...
        }
    }
    

    وهذا يعني أن البنية دائما instantiable في حين أن فئة قد لا يكون لأن جميع المنشئات يمكن أن تكون خاصة.

    class NonInstantiable
    {
        private NonInstantiable() // OK
        {
        }
    }
    
    struct Direct
    {
        private Direct() // Compile-time error
        {
        }
    }
    
  4. البنية لا يمكن أن يكون المدمر.وهو المدمر هو مجرد تجاوز من وجوه.اللمسات الأخيرة في تمويه ، و البنيات ، ويجري أنواع قيمة ، لا تخضع جمع القمامة.

    struct Direct
    {
        ~Direct() {} // Compile-time error
    }
    class InDirect
    {
        ~InDirect() {} // Compiles OK
    }
    
    And the CIL for ~Indirect() looks like this:
    
    .method family hidebysig virtual instance void
            Finalize() cil managed
    {
      // ...
    } // end of method Indirect::Finalize
    
  5. البنية ضمنيا مختومة ، فئة لا.
    البنية لا يمكن أن تكون مجردة ، ويمكن فئة.
    البنية لا يمكن الاتصال :قاعدة() في منشئ بينما فئة دون صريحة قاعدة الفئة.
    البنية لا يمكن تمديد فئة أخرى ، يمكن أن فئة.
    البنية لا يمكن أن تعلن محمية أعضاء (على سبيل المثال ، حقول متداخلة أنواع) فئة يمكن.
    البنية لا يمكن أن تعلن مجردة وظيفة أعضاء فئة مجردة يمكن.
    البنية لا يمكن أن تعلن الظاهري وظيفة أعضاء فئة يمكن.
    البنية لا يمكن أن تعلن مختومة وظيفة أعضاء فئة يمكن.
    البنية لا يمكن أن تعلن تجاوز وظيفة أعضاء فئة يمكن.
    الاستثناء الوحيد لهذه القاعدة هو أن البنية يمكن تجاوز الظاهري أساليب النظام.كائن ، أي ما يعادل () ، GetHashCode () ، ToString().

كما ذكر سابقا:الطبقات هي نوع مرجع حين البنيات هي أنواع قيمة مع كل العواقب.

مثل الإبهام من القاعدة إطار تصميم المبادئ التوجيهية توصي باستخدام البنيات بدلا من الفصول إذا:

  • وقد مثيل الحجم تحت 16 بايت
  • ذلك منطقيا يمثل قيمة واحدة ، على غرار أنواع بدائية (int, double, الخ.)
  • هو غير قابل للتغيير
  • فإنه لن يكون محاصر في كثير من الأحيان
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|                       |                                                Struct                                                |                                               Class                                               |
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
| Type                  | Value-type                                                                                           | Reference-type                                                                                    |
| Where                 | On stack / Inline in containing type                                                                 | On Heap                                                                                           |
| Deallocation          | Stack unwinds / containing type gets deallocated                                                     | Garbage Collected                                                                                 |
| Arrays                | Inline, elements are the actual instances of the value type                                          | Out of line, elements are just references to instances of the reference type residing on the heap |
| Aldel Cost            | Cheap allocation-deallocation                                                                        | Expensive allocation-deallocation                                                                 |
| Memory usage          | Boxed when cast to a reference type or one of the interfaces they implement,                         | No boxing-unboxing                                                                                |
|                       | Unboxed when cast back to value type                                                                 |                                                                                                   |
|                       | (Negative impact because boxes are objects that are allocated on the heap and are garbage-collected) |                                                                                                   |
| Assignments           | Copy entire data                                                                                     | Copy the reference                                                                                |
| Change to an instance | Does not affect any of its copies                                                                    | Affect all references pointing to the instance                                                    |
| Mutability            | Should be immutable                                                                                  | Mutable                                                                                           |
| Population            | In some situations                                                                                   | Majority of types in a framework should be classes                                                |
| Lifetime              | Short-lived                                                                                          | Long-lived                                                                                        |
| Destructor            | Cannot have                                                                                          | Can have                                                                                          |
| Inheritance           | Only from an interface                                                                               | Full support                                                                                      |
| Polymorphism          | No                                                                                                   | Yes                                                                                               |
| Sealed                | Yes                                                                                                  | When have sealed keyword                                                                          |
| Constructor           | Can not have explicit parameterless constructors                                                     | Any constructor                                                                                   |
| Null-assignments      | When marked with nullable question mark                                                              | Yes (+ When marked with nullable question mark in C# 8+)                                          |
| Abstract              | No                                                                                                   | When have abstract keyword                                                                        |
| Access Modifiers      | public, private, internal                                                                            | public, protected, internal, protected internal, private protected                                |
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+

البنيات هي القيمة الفعلية - أنها يمكن أن تكون فارغة ولكن لم null

هذا صحيح ، لكن أيضا ملاحظة أنه اعتبارا من .صافي 2 البنيات دعم Nullable النسخة و C# الإمدادات بعض نحوي السكر لجعله أسهل للاستخدام.

int? value = null;
value  = 1;

هناك قضية واحدة مثيرة للاهتمام من "الطبقة مقابل البنية" لغز الوضع عندما كنت في حاجة للعودة إلى عدة نتائج من طريقة:اختيار لاستخدام.إذا كنت تعرف ValueTuple القصة - أنت تعرف أن ValueTuple (البنية) وأضيف لأنه يجب أن يكون أكثر فعالية ثم المجموعة (الطبقة).ولكن ماذا يعني ذلك في الأرقام ؟ اختبارين:واحد هو البنية/الطبقة التي تحتوي على 2 حقول أخرى مع البنية/الطبقة التي تحتوي 8 حقول (مع البعد أكثر من 4 - الفئة ينبغي أن تصبح أكثر فعالية ثم البنية من حيث المعالج القراد ، ولكن بالطبع GC الحمل أيضا ينبغي النظر).

P. S.آخر مؤشر على حالة محددة 'sturct أو فئة مع مجموعات' هناك: https://stackoverflow.com/a/45276657/506147

BenchmarkDotNet=v0.10.10, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233540 Hz, Resolution=309.2586 ns, Timer=TSC
.NET Core SDK=2.0.3
  [Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
  Clr    : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2115.0
  Core   : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT


            Method |  Job | Runtime |     Mean |     Error |    StdDev |      Min |      Max |   Median | Rank |  Gen 0 | Allocated |
------------------ |----- |-------- |---------:|----------:|----------:|---------:|---------:|---------:|-----:|-------:|----------:|
  TestStructReturn |  Clr |     Clr | 17.57 ns | 0.1960 ns | 0.1834 ns | 17.25 ns | 17.89 ns | 17.55 ns |    4 | 0.0127 |      40 B |
   TestClassReturn |  Clr |     Clr | 21.93 ns | 0.4554 ns | 0.5244 ns | 21.17 ns | 23.26 ns | 21.86 ns |    5 | 0.0229 |      72 B |
 TestStructReturn8 |  Clr |     Clr | 38.99 ns | 0.8302 ns | 1.4097 ns | 37.36 ns | 42.35 ns | 38.50 ns |    8 | 0.0127 |      40 B |
  TestClassReturn8 |  Clr |     Clr | 23.69 ns | 0.5373 ns | 0.6987 ns | 22.70 ns | 25.24 ns | 23.37 ns |    6 | 0.0305 |      96 B |
  TestStructReturn | Core |    Core | 12.28 ns | 0.1882 ns | 0.1760 ns | 11.92 ns | 12.57 ns | 12.30 ns |    1 | 0.0127 |      40 B |
   TestClassReturn | Core |    Core | 15.33 ns | 0.4343 ns | 0.4063 ns | 14.83 ns | 16.44 ns | 15.31 ns |    2 | 0.0229 |      72 B |
 TestStructReturn8 | Core |    Core | 34.11 ns | 0.7089 ns | 1.4954 ns | 31.52 ns | 36.81 ns | 34.03 ns |    7 | 0.0127 |      40 B |
  TestClassReturn8 | Core |    Core | 17.04 ns | 0.2299 ns | 0.2150 ns | 16.68 ns | 17.41 ns | 16.98 ns |    3 | 0.0305 |      96 B |

كود الاختبار:

using System;
using System.Text;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Columns;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using DashboardCode.Routines.Json;

namespace Benchmark
{
    //[Config(typeof(MyManualConfig))]
    [RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
    [ClrJob, CoreJob]
    [HtmlExporter, MarkdownExporter]
    [MemoryDiagnoser]
    public class BenchmarkStructOrClass
    {
        static TestStruct testStruct = new TestStruct();
        static TestClass testClass = new TestClass();
        static TestStruct8 testStruct8 = new TestStruct8();
        static TestClass8 testClass8 = new TestClass8();
        [Benchmark]
        public void TestStructReturn()
        {
            testStruct.TestMethod();
        }

        [Benchmark]
        public void TestClassReturn()
        {
            testClass.TestMethod();
        }


        [Benchmark]
        public void TestStructReturn8()
        {
            testStruct8.TestMethod();
        }

        [Benchmark]
        public void TestClassReturn8()
        {
            testClass8.TestMethod();
        }

        public class TestStruct
        {
            public int Number = 5;
            public struct StructType<T>
            {
                public T Instance;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance;
            }

            private StructType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private StructType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private StructType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private StructType<int> Method4(int i)
            {
                var x = new StructType<int>();
                x.List = new List<string>();
                x.Instance = ++i;
                return x;
            }
        }

        public class TestClass
        {
            public int Number = 5;
            public class ClassType<T>
            {
                public T Instance;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance;
            }

            private ClassType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private ClassType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private ClassType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private ClassType<int> Method4(int i)
            {
                var x = new ClassType<int>();
                x.List = new List<string>();
                x.Instance = ++i;
                return x;
            }
        }

        public class TestStruct8
        {
            public int Number = 5;
            public struct StructType<T>
            {
                public T Instance1;
                public T Instance2;
                public T Instance3;
                public T Instance4;
                public T Instance5;
                public T Instance6;
                public T Instance7;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance1;
            }

            private StructType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private StructType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private StructType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private StructType<int> Method4(int i)
            {
                var x = new StructType<int>();
                x.List = new List<string>();
                x.Instance1 = ++i;
                return x;
            }
        }

        public class TestClass8
        {
            public int Number = 5;
            public class ClassType<T>
            {
                public T Instance1;
                public T Instance2;
                public T Instance3;
                public T Instance4;
                public T Instance5;
                public T Instance6;
                public T Instance7;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance1;
            }

            private ClassType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private ClassType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private ClassType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private ClassType<int> Method4(int i)
            {
                var x = new ClassType<int>();
                x.List = new List<string>();
                x.Instance1 = ++i;
                return x;
            }
        }
    }
}

كل متغير أو مجال البدائية القيمة نوع أو نوع الهيكل يحمل فريدة من نوعها سبيل المثال من هذا النوع ، بما في ذلك جميع الحقول (العامة والخاصة).وعلى النقيض من ذلك ، المتغيرات أو حقول من أنواع المراجع قد عقد باطل ، أو قد تشير إلى كائن ، مخزنة في مكان آخر ، أي عدد من المراجع الأخرى قد تكون موجودة أيضا.مجالات البنية سيتم تخزينها في نفس المكان متغير أو حقل من نوع الهيكل ، والتي قد تكون إما على المكدس أو قد يكون جزء من آخر كومة الكائن.

إنشاء متغير أو مجال البدائية نوع القيمة سيخلق ذلك مع قيمة افتراضية ؛ إنشاء متغير أو حقل من نوع الهيكل سيتم إنشاء مثيل جديد ، وخلق جميع الحقول الواردة في الطريقة الافتراضية.خلق جديد سبيل المثال من نوع مرجع سوف تبدأ من خلال خلق جميع الحقول الواردة في الطريقة الافتراضية ثم تشغيل اختياري رمز إضافية اعتمادا على نوع.

نسخ متغير واحد أو حقل من نوع بدائي إلى آخر نسخ القيمة.نسخ متغير واحد أو مجال هيكل نوع إلى آخر نسخ جميع المجالات (العام والخاص) من الحالة الأولى إلى الحالة الثانية.نسخ متغير واحد أو حقل من نوع مرجع إلى آخر سوف يسبب هذا الأخير أن أشير إلى نفس المثال السابق (إن وجد).

من المهم أن نلاحظ أنه في بعض اللغات مثل C++ ، الدلالي السلوك من نوع مستقل عن كيفية تخزينها, ولكن هذا ليس صحيحا .صافي.إذا كان نوع تنفذ قابلة للتغيير قيمة دلالات نسخ متغير واحد من نوع إلى آخر نسخ خصائص أولا إلى حالة أخرى ، أشار إليه الثانية ، واستخدام عضو الثانية على التحور فإنه سوف يسبب تلك الدرجة الثانية إلى تغيير ، ولكن ليس من الأول.إذا كان نوع تنفذ قابلة للتغيير الإشارة دلالات نسخ متغير واحد إلى آخر باستخدام عضو الثانية على التحور الكائن سوف تؤثر على الكائن الذي أشار إليه أولا متغير ؛ أنواع ثابتة دلالات لا تسمح الطفرة ، لذلك لا يهم لغويا سواء نسخ أو إنشاء مثيل جديد أو يخلق إشارة أخرى إلى الأول.

في .صافي فمن الممكن القيمة أنواع لتنفيذ أي من أعلاه دلالات ، شريطة أن جميع الحقول يمكن أن تحذو حذوها.نوع مرجع ، ومع ذلك ، يمكن فقط تنفيذ قابلة للتغيير الإشارة دلالات أو ثابتة دلالات;أنواع قيمة مع حقول قابلة للتغيير أنواع مرجع تقتصر إما على تنفيذ قابلة للتغيير الإشارة دلالات أو غريب هجين دلالات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top