在 C# 中,为什么 'is' 运算符在以下情况下会出现这样的行为?

问题描述 投票:0回答:2

我在 .Net6 控制台应用程序中有以下代码。

internal class Program

    {

        static void Main(string[] args)

        {

            var x = new SomethingUser<Something>();

            var y = new SomethingUser<ISomething>();

 

            Console.WriteLine(x is ISomethingUser<Something>);

            Console.WriteLine(y is ISomethingUser<ISomething>);

            Console.WriteLine(x is SomethingUser<ISomething>);

            Console.WriteLine(y is SomethingUser<ISomething>);

 

            Console.Read();

        }

    }


    public class Something : ISomething {}

    public class SomethingUser<T> : ISomethingUser {}

    public interface ISomething {}
 
    public interface ISomethingUser<T> {}
}

实际输出为: 真的, 真的, 错误的, 正确

有人可以解释为什么第三种情况下 is 检查评估结果为 false 吗?

我期望的输出是: 真的, 真的, 真的, 正确

c# operators
2个回答
1
投票

因为

SomethingUser<Something>
SomethingUser<ISomething>
是不同的类型。 C# 仅对接口和委托的泛型参数具有协变性,而对类则不具有协变性。

来自 ECMA-334 C# 标准第 6 版,第 1 章17.2.3.1:

变体类型参数列表只能出现在接口和委托类型上。

...

如果方差注释为

out
,则称类型参数是协变的。

顺便说一句,您可以通过为泛型参数

ISomethingUser
添加
out
规范来声明
public interface ISomethingUser<out T> {}
为协变,从而稍微提高兼容性,然后
x is ISomethingUser<ISomething>
将返回
true
。因此,通过转换为接口,类仍然没有协变性。


0
投票

类型测试运算符和强制转换表达式 - is、as、typeof 和强制转换:

当表达式结果非空且满足以下任一条件时,is 运算符返回 true:

  • 表达式结果的运行时类型是T。
  • 表达式结果的运行时类型派生自类型 T、实现接口 T,或者存在从它到 T 的另一个隐式引用转换
  • 表达式结果的运行时类型是可空值类型,其基础类型为 T,并且 Nullable.HasValue 为 true。
  • 存在从表达式结果的运行时类型到类型 T 的装箱或拆箱转换。
© www.soinside.com 2019 - 2024. All rights reserved.