هل يؤدي استدعاء أسلوب على نوع قيمة إلى الملاكمة في .NET؟

StackOverflow https://stackoverflow.com/questions/436363

  •  22-07-2019
  •  | 
  •  

سؤال

لقد كنت أشارك للتو في سؤال Stack Overflow هل كل شيء في .NET كائن؟.

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

أنا لا أثق بمصدر واحد، لذلك أردت فقط الحصول على مزيد من التعليقات حول هذا السؤال.حدسي هو أنه لا توجد ملاكمة ولكن حدسي سيء.:د

لمزيد من التفصيل:

المثال الذي استخدمته كان:

int x = 5;
string s = x.ToString(); // Boxing??

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

ومع ذلك، إذا لم تتجاوز البنية الطريقة، فسيتم إنشاء "قيد" CIL يتم تنفيذ الأمر قبل callvirt.ووفقا للوثائق، OpCodes.الحقل المقيد, ينتج عن هذا الملاكمة:

إذا كان هذا النوع هو نوع قيمة ولا يقوم This -type بتنفيذ الطريقة ، فسيتم إزالة ptr ، محاصر ، وتم تمريره كمؤشر إلى تعليمات طريقة callvirt.

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

المحلول

وهنا يكمن IL للالتعليمات البرمجية:

L_0001: ldc.i4.5      // get a 5 on the stack
L_0002: stloc.0       // store into x
L_0003: ldloca.s x    // get the address of x on the stack
L_0005: call instance string [mscorlib]System.Int32::ToString()  // ToString
L_000a: stloc.1       // store in s

وهكذا كان الجواب في هذه الحالة هو لا.

نصائح أخرى

وفي حالة أنك أعطيت الجواب لا، كما أشار القاعدة.

ومع ذلك، سيتم ذلك إذا قمت باستدعاء أسلوب من خلال مؤشر الواجهة.

خذ بعين الاعتبار الكود:

interface IZot
{
    int F();
}

struct Zot : IZot
{
    public int F()
    {
        return 123;
    }
}

ثم

Zot z = new Zot();
z.F();

يفعل لا النتيجة في الملاكمة:

.locals init (
    [0] valuetype ConsoleApplication1.Zot z)
L_0000: nop 
L_0001: ldloca.s z
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloca.s z
L_000b: call instance int32 ConsoleApplication1.Zot::F()
L_0010: pop 
L_0011: ret 

ومع ذلك، هذا يفعل:

IZot z = new Zot();
z.F();

   .locals init (
        [0] class ConsoleApplication1.IZot z,
        [1] valuetype ConsoleApplication1.Zot CS$0$0000)
    L_0000: nop 
    L_0001: ldloca.s CS$0$0000
    L_0003: initobj ConsoleApplication1.Zot
    L_0009: ldloc.1 
    L_000a: box ConsoleApplication1.Zot
    L_000f: stloc.0 
    L_0010: ldloc.0 
    L_0011: callvirt instance int32 ConsoleApplication1.IZot::F()
    L_0016: pop 

ggf31316

<اقتباس فقرة>   

وقال "اعتقد ان يدعو ToString،   يساوي وGethashcode نتيجة في   الملاكمة إذا كانت بنية لا   تجاوز الطرق ".

ولقد راجعت ToString بالنسبة لك. Int32 لا تجاوز ToString، لذلك جعل البنية لا. اعتدت . NET العاكس لضمان أن البنية لا تجاوز بطريقة أو بأخرى سحرية ToString () ، وأنه لم يكن.

وهكذا كان رمز مثل هذا:

using System;

namespace ConsoleApplication29
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStruct ms = new MyStruct(5);
            string s = ms.ToString();
            Console.WriteLine(s);
        }
    }

    struct MyStruct
    {
        private int m_SomeInt;

        public MyStruct(int someInt)
        {
            m_SomeInt = someInt;
        }

        public int SomeInt
        {
            get
            {
                return m_SomeInt;
            }
        }
    }
}

وعلى MSIL (عبر ILDASM ) عن الأسلوب الرئيسي هو هذا:

  IL_0000:  ldloca.s   ms
  IL_0002:  ldc.i4.5
  IL_0003:  call       instance void ConsoleApplication29.MyStruct::.ctor(int32)
  IL_0008:  ldloca.s   ms
  IL_000a:  constrained. ConsoleApplication29.MyStruct
  IL_0010:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0015:  stloc.1
  IL_0016:  ldloc.1
  IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001c:  ret

والآن، على الرغم من عدم وجود مكالمة الملاكمة تجري، إذا قمت بالتدقيق <لأ href = "http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.constrained.aspx" يختلط = "نوفولو noreferrer"> وثائق حول مقيدة + مكالمة virt ، وسوف تجد أنها تنص على أن الملاكمة لا تأخذ مكان. OOO

اقتباس:

<اقتباس فقرة>   

إذا thisType هو نوع القيمة و   thisType لا تطبق طريقة   ثم PTR ألغى الإشارة القيمة، ومحاصر، و   مرت باسم 'هذا' مؤشر ل   تعليم طريقة callvirt.

وأعتقد أن يدعو ToString، يساوي وGethashcode النتيجة في الملاكمة إذا كانت بنية لا يتجاوز الطرق.

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