Что означает «это» в C #? - PullRequest
       1

Что означает «это» в C #?

1 голос
/ 03 августа 2011

На стр.170 «CLR via C #»:


public sealed class Program {
    public Int32 GetFive() { return 5; }
    public static void Main() {
       Program p = null;
       Int32 x = p.GetFive(); // In C#, NullReferenceException is thrown
    }
}

Теоретически, код выше в порядке. Конечно, переменная p равна нулю, но при вызове не виртуальной Метод (GetFive), CLR должен знать только тип данных p, который является программой. Если GetFive действительно вызывается, значение этого аргумента будет нулевым. Поскольку аргумент не используется внутри метода GetFive, не генерируется исключение NullReferenceException.


Прошу прощения за мою глупость. Я помню, что CLR действительно находит код метода по 'this', который всегда косвенно появляется в первом аргументе метода delcare, почему он говорит 'при вызове не виртуального Метод (GetFive), CLR должен знать только тип данных p '?

Ответы [ 3 ]

5 голосов
/ 03 августа 2011

CLR не выполняет нулевые проверки для не виртуальных методов.По сути, если метод вызывается с инструкцией call, CLR не проверяет нулевой указатель this.Напротив, инструкция callvirt всегда проверяет на ничтожность.Однако C # выдает инструкцию callvirt независимо от того, является ли метод виртуальным.

Что говорит отрывок, так это то, что если компилятор C # выпустил более семантически подходящую инструкцию call вместо инструкции callvirt для не виртуальных методов, то рассматриваемый код не выдаст NullReferenceException,Насколько я помню, команда компиляторов решила почти всегда выдавать инструкцию callvirt, поскольку она лучше справлялась с управлением версиями (также JIT может оптимизировать callvirt в call).

См. http://www.pvle.be/tag/clr/

3 голосов
/ 03 августа 2011

this относится к текущему самому экземпляру (классу).

Ваш фрагмент кода,

Program p = null;
Int32 x = p.GetFive(); // In C#, NullReferenceException is thrown

не работает, потому что вы пытаетесь вызвать метод GetFive of null, несуществующий экземпляр Program - другими словами, вы пытаетесь постучать в дверь пустоты, дверь, которая не существует.Поскольку CLR не знает местоположение двери, оно выдает исключение "не могу найти функциональную дверь!"для вас - намного лучше, чем неопределенное поведение.

0 голосов
/ 03 августа 2011

Хорошо. Я только что посмотрел стр. 170 CLR через C #, 3-е издание.

Возможно, весь смысл страницы в разделе ВАЖНО , в котором другой компилятор языка CLR генерирует некоторый код, который использует ваш класс C #, а затем вы изменяете свой код C # на не виртуальный метод без перекомпиляции кода, ссылающегося на библиотеку C #. В этом случае у вас может возникнуть проблема в зависимости от того, реализует ли вызывающий объект вызов или callvirt (не определено, что будет делать этот компилятор).

c # всегда по умолчанию callvirt, так что никаких проблем нет, но для звонящего вы не можете знать это заранее. Если вы сделаете это, вы можете непреднамеренно прервать чью-либо другую программу, если отправляете библиотеки или API.


Попробуйте вместо этого.

    public static Int32 GetFive() { return 5; }    
    public static void Main() {       
        Int32 x = GetFive(); 
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...