there is an operator that behaves strangely

1) According to my book, the is operator can verify that the expression E ( E is type ) can be converted to the target type only if E is either a reference transformation, or a box, or an unpack. Since in the following example, is does not check any of the three conversion types, the code should not work, but it:

  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)

a)

  B b; A a = new A(); if (a is B) b = (B)a; int i = bl; class A { public int l = 100; } class B:A { } 

The above code always causes a compile-time error "Use of unassigned variable" . If the condition a is B evaluates to false , then b will not be assigned a value, but if the condition is true , then it will be. And thus, by allowing such a code compiler, there is no way to find out if using b in the code following the if is valid or not (because it doesn't know if a is B true or false ) but why would he know that? Intsead why can't runtime handle this?

b) But if instead they were dealing with non-reference types, then the compiler does not complain, although the code is identical. Why?

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

Thank you

+4
source share
5 answers

The real difference is that in the case of int you are talking about a specific field purpose ( l ). Fields are always assigned (even without =100 ). In case B you are talking about a specific assignment to a local variable ( B ); local variables do not start as specifically assigned.

That is all there is.


int i = 100; if (i long) // returns true, indicating that a conversion is possible

1: I do not think this returns true at all; for me, this shows an IDE warning to never be true. Looking at the reflector, the compiler completely removes this branch. I assume that the compiler must at least compile on the basis that it could (theoretically) field and test. But he already knows the answer, so he cuts it off.

2: I still get the unassigned variable compiler error; due to a "specific assignment"

+3
source

This has nothing to do with the is operator. The compiler sees that there are two possible paths, only one of which assigns the value b .

When working with value types, the compiler knows that l implicitly initialized to 0 .

+6
source

The compiler behaves correctly - why compile without errors if there is a use of an unassigned variable? You cannot work with bl unless b is assigned, as the compiler checks that there is a path to the code that does not instantiate b , so it throws an error ...

+2
source

In your code, class B comes from A. This means:

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

This means that the body of the if block will not be entered, and b will not be assigned.

Stephen Cleary also has a point. I do not know how complicated the compiler is in evaluating whether values ​​are assigned.

+2
source

Ok, MSDN says is :

Operator used to check if the runtime type is compatible with this type.

An expression expresses true if both of the following conditions are true:

  • expression is not null .
  • expression can be dropped to type . That is, an expression for a form expression (type)(expression) will end without exception.

This will go well with 1, but 2 is another topic and the right one (think about it).

However, the following code writes 0 to the output:

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

Therefore, it seems that the MSDN documentation note is also true:

Note that the is operator only considers links, box conversions and unboxing conversions. Other conversions, such as custom conversions, are not considered by the is operator.

+2
source

Source: https://habr.com/ru/post/1312791/


All Articles