2010-06-14 3 views
4

1) В соответствии с моей книгой, is оператор может проверить, является ли выражение E (E is type) может быть преобразован в целевой тип, только если E является либо ссылочное преобразование, бокс или распаковка. Так как в следующем примере is не проверяет ни для одного из трех типов преобразования, код не должен работать, но это делает:«является» оператор ведет себя немного странно

long l;  // EDIT - I forgot to add this line of code in my initial post 
    int i=100; 
    if (i is long) //EDIT - in my initial post I've claimed condition returns true, but it really returns false 
      l = i; 

2)

а)

B b; 
    A a = new A(); 
    if (a is B) 
     b = (B)a; 
    int i = b.l; 


    class A { public int l = 100; } 
    class B:A { } 

Приведенный выше код всегда вызывает ошибку времени компиляции “Use of unassigned variable”. Если условие a is B оценивается как false, то b не будет присвоено значение, но при условии true, то это будет. И таким образом, разрешив такой компилятор кода, не будет знать, является ли использование b в коде, следующем за оператором if, действительным или нет (из-за того, что не знает, a is b оценивает true или false), но зачем ему это знать? Intsead, почему это невозможно?

b) Но если вместо этого мы имеем дело с не ссылочными типами, то компилятор не жалуется, хотя код идентичен. Почему?

 int i = 100; 
     long l; 
     if (i is long) 
      l = i; 

спасибо

+1

Лично я удивлен, что '(i long) == true'. Однако поведение (2) совершенно прямолинейно. –

+0

BTW, C# чувствителен к регистру. Нет оператора 'IS'. –

+0

@JS Bangs - простой: это не так. –

ответ

3

Реальная разница в том, что в int случае, вы говорите о определенном присвоении поля (l). Поля всегда определенно присвоены (даже без =100). В случае B вы говорите об определенном присвоении локальной переменной (b); локальные переменные do не начинаются как определенно назначенные.

Вот и все.


INT I = 100; если (я долго) // возвращает истину, показывая, что преобразование возможно

1: Я не думаю, что это возвращает trueна всех; для меня это показывает предупреждение IDE о том, чтобы никогда не быть правдой. Глядя в отражатель, компилятор полностью удаляет эту ветвь. Я думаю, компилятор обязан по крайней мере компилировать на том основании, что он мог (теоретически) полем и тесту. Но он уже знает ответ, поэтому он обрезает его.

2: Я все еще получаю ошибку компилятора «неназначенная переменная»; из-за «определенного назначения»

+0

1) «Реальное различие заключается в том, что в случае int вы говорите об определенном задании поля (1). Поля всегда назначаются (даже без = 100). В случае B вы говорите об определенном назначении локальной переменной (b); локальные переменные не начинаются как определенно назначенные ». Я сделал ошибку в своем исходном сообщении, так как я не включил код, который ясно показывает, что переменная l (как используется в моем первом вопросе) является локальной переменной (будет редактировать мой пост).Таким образом, зная, что l (в случае int) является локальной переменной, l не получает инициализацию до значения 0 – flockofcode

+0

2) «Я не думаю, что это вообще возвращает true». Моя ошибка, я забыл добавить {} и вместо того, чтобы иметь (i длинный) {l = i; Console.WriteLine ("something");} У меня было ... 3) «Я все еще получаю ошибку компилятора« неназначенная переменная »; из-за «определенного задания» «На какой вопрос вы имеете в виду? – flockofcode

+1

@flockofcode - ну, я неявно предположил, что у вас также есть код, который пытается * использовать * 'l' ... –

6

Это не имеет никакого отношения к оператору is. Компилятор видит, что существует два возможных пути, только один из которых назначит значение b.

При использовании типов значений компилятор знает, что l получает неявное инициализацию до значения 0.

+0

«При работе со типами значений компилятор знает, что я получает неявное инициализацию до значения 0.» Я сделал ошибку в своем исходном сообщении, так как я не включил код, который ясно показывает, что переменная l (как используется в моем первом вопросе) является локальной переменной (будет редактировать мой пост). Таким образом, зная, что l не получает инициализацию до значения 0 – flockofcode

+1

@flockofcode, типы значений по сути инициализируются и время декларации, даже если они являются локальными переменными. Ссылочных типов нет. –

+1

Я, вероятно, пропущу точку, которую вы пытаетесь передать, но в любом случае ... если вы говорите правильно, то почему следующий код приводит к «использованию неназначенной локальной переменной a1» -> int a1 ; int a2 = a1; Если a1 был действительно инициализирован во время объявления, то почему компилятор сообщил об ошибке, когда мы попытались присвоить значение a1 переменной a2 ?! – flockofcode

2

Компилятор ведет себя правильно - почему он должен компилироваться без ошибок, если является использованием неназначенной переменной? Вы не можете работать с b.l если b не назначается, как компилятор проверяет, что есть путь кода, который не создает экземпляр b именно поэтому он выдает ошибку ...

2

В коде, класс B является производным от А. Это означает, :

a is B // evaluates to false 
b is A // evaluates to true 

Это означает, что тело if блока не будет введен, и б не будет назначен.

У Стивена Клири также есть точка. Я не знаю, насколько сложным является компилятор при оценке того, назначены ли значения.

2

Хорошо, MSDN говорит о is:

является оператор используется для проверки, является ли тип времени выполнения объекта совместим с данным типом.

Ап выражение истинно, если оба из следующих условий:

  • выражения не нуля.
  • выражение может быть отлито до тип. То есть, литое выражение формы (type)(expression) завершится без исключения исключения.

Это будет соответствовать довольно хорошо с 1, но 2 другая тема и правильно (думать об этом).

Однако следующий код записывает 0 на выход:

int i = 1; 
    long l = 0; 
    if (i is long) { 
     l = i; 
    } 
    Console.WriteLine(l); 

Поэтому кажется, что банкнота в MSDN документации is правильно, а также:

Обратите внимание, что только оператор рассматривает конверсии ссылок, конверсии бокса и распаковывание конверсий. Другие преобразования, такие как пользовательские преобразования, не рассматриваются оператором is.

+0

Я думаю, что слово «время исполнения» является важным отличием здесь. Компилятор не работает во время выполнения, и он не будет делать вывод, что a является B. С примитивами они всегда инициализируются. –

+0

Да, я имел в виду, что * поведение * компилятора верное. Извините, если это неясно. – Lucero