我在 .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 吗?
我期望的输出是: 真的, 真的, 真的, 正确
因为
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
。因此,通过转换为接口,类仍然没有协变性。
类型测试运算符和强制转换表达式 - is、as、typeof 和强制转换:
当表达式结果非空且满足以下任一条件时,is 运算符返回 true: