Ограниченный вызов IL

Для этого кода:

class Program
{
    static void Main()
    {
        Console.WriteLine(new MyStruct().ToString());
    }

    struct MyStruct { }
}

компилятор C# генерирует constrained callvirt IL-кода.

В В этой статье говорится:

Например, если тип значения V переопределяет метод Object.ToString(), выдается инструкция call V.ToString(); если это не так, генерируется инструкция box и инструкция callvirt Object.ToString(). Проблема управления версиями может возникнуть ‹...>, если позднее будет добавлено переопределение.

Итак, мой вопрос: почему в этом случае может возникнуть проблема, если компилятор сгенерирует код box, а не вызов с ограничениями?


person aush    schedule 08.02.2015    source источник
comment
разве ссылка, которую вы предоставили, уже не объясняет это, прямо перед вашей цитатой: использование префикса constrained также позволяет избежать потенциальных проблем с версиями с типами значений. Если ограниченный префикс не используется, должен быть создан другой IL в зависимости от того, переопределяет ли тип значения метод System.Object.   -  person Selman Genç    schedule 08.02.2015
comment
@ Selman22, поэтому и спрашиваю. Я не понимаю, почему это не может быть просто callvirt для обоих случаев.   -  person aush    schedule 08.02.2015


Ответы (1)


Инструкция box создает копию рассматриваемого экземпляра. Методам экземпляра значимых типов разрешено изменять экземпляр, к которому они вызываются, и если они это делают, молчаливый вызов метода для копии — неправильный поступок.

static class Program
{
    static void Main()
    {
        var myStruct = new MyStruct();
        Console.WriteLine(myStruct.i); // prints 0
        Console.WriteLine(myStruct.ToString()); // modifies myStruct, not a copy of myStruct
        Console.WriteLine(myStruct.i); // prints 1
    }

    struct MyStruct {
        public int i;
        public override string ToString() {
            i = 1;
            return base.ToString();
        }
    }
}
person Community    schedule 08.02.2015