“是”操作员表现得有些奇怪

时间:2010-06-14 19:32:00

标签: c# .net

1)根据我的书,is运营商可以检查是否 仅当E是引用转换,装箱或拆箱时,表达式E is typeE)才能转换为目标类型。由于在以下示例中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)

a)

    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是否评估为truefalse),但为什么要知道呢? Intsead为什么不能运行时处理这个?

b)但是如果相反我们处理非引用类型,那么编译器不会抱怨,即使代码是相同的。为什么?

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

谢谢

5 个答案:

答案 0 :(得分:6)

这与is运算符无关。编译器发现有两个可能的路径,其中只有一个路径会将值赋给b

在处理值类型时,编译器知道l被隐式初始化为值0

答案 1 :(得分:3)

真正的区别在于,int案例中,您正在讨论明确指定字段l)。字段始终明确分配(即使没有=100)。在B案例中,您谈论的是局部变量b)的明确分配;局部变量 not 以明确分配的方式启动。

就是这样。


  

int i = 100;     if(i is long)//返回true,表示转换是可能的

1:我认为这根本不会返回true ;对我来说,它显示了一个关于永远不会是真的IDE警告。查看反射器,编译器会完全删除此分支。我想编译器必须至少编译,理由是它(在理论上)可以进行框和测试。但它已经知道了答案,所以它会剪掉它。

2:我仍然得到“未分配的变量”编译器错误;由于“明确的任务”

答案 2 :(得分:2)

编译器行为正确 - 如果 使用未分配的变量,为什么编译时没有错误?如果b.l未分配,则无法使用b,因为编译器会检查是否存在未实例化b的代码路径,这就是它抛出错误的原因...

答案 3 :(得分:2)

在你的代码中,B类派生自A.这意味着:

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

这意味着不会输入if块的正文,也不会指定b。

Stephen Cleary也有一点意见。在评估是否分配了值时,我不知道编译器的复杂程度。

答案 4 :(得分:2)

好的,MSDN在is上说:

  

运算符用于检查对象的运行时类型是否与给定类型兼容。

     

如果满足以下两个条件,则表达式的计算结果为true:

     
      
  • 表达式不是 null
  •   
  • 表达式可以转换为类型。也就是说,(type)(expression)形式的强制转换表达式将在不抛出异常的情况下完成。
  •   

这与1非常吻合,但2是另一个主题并且正确(想一想)。

但是,以下代码将0写入输出:

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

因此,is MSDN文档中的注释似乎也是正确的:

  

请注意,is运算符仅考虑引用转换,装箱转换和取消装箱转换。 is运算符不会考虑其他转换,例如用户定义的转换。