通用类型冲突?

Roy*_*mir 9 .net c# generics type-safety

我看到了这个有趣的问题 ,它讨论T了类级别的声明和T方法级别的相同字母(不同的含义).

所以我做了一个测试.

  static void Main(string[] args)
        {
            var c = new MyClass<int>(); //T is int
            c.MyField = 1;
            c.MyProp = 1;
            c.MyMethod("2");
        }


        public class MyClass<T>
        {
            public T MyField;
            public T MyProp { get; set; }
            public void MyMethod<T>(T k)
            {
            }
        }
Run Code Online (Sandbox Code Playgroud)

正如埃里克所说,编译器会发出警告.

但是,嘿,安全类型怎么了?我假设在Method级别有一个类型安全,但是已经声明的类的全局上下文呢T.

我的意思是如果有人会问我,我猜应该有错误,而不是警告.

编译器为什么允许这样做?(我很乐意听到一个合理的答案)

Rys*_*gan 3

有趣的问题。这里保留了类型安全。行为类似于全局变量和局部变量。在MyMethod中,类型T是明确的。我们还可以创建并返回MyClass的新实例,如下所示:

public class MyClass<T>
{
    public T MyField;
    public T MyProp { get; set; }
    public MyClass<T> MyMethod<T>(T k)
    {
        return new MyClass<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序:

static void Main()
{
    var c = new MyClass<int>(); //T is int
    c.MyField = 1;
    c.MyProp = 1;

    var myClass = c.MyMethod("2");
    myClass.MyField = "2";
    myClass.MyField = "4";
}
Run Code Online (Sandbox Code Playgroud)

不存在编译错误,也不应该出现编译错误,因为保留了类型安全。程序可以编译。没有任何歧义。

警告应该在那里,因为T覆盖了其类级别对应项,并且MyMethod中没有简单的方法来获取全局T。它还模糊了易读性。

MSDN 介绍了通用方法(C# 编程指南)中的灵活性和良好实践:

如果您定义的泛型方法采用与包含类相同的类型参数,则编译器会生成警告 CS0693,因为在方法范围内,为内部 T 提供的参数隐藏了为外部 T 提供的参数。如果您需要以下灵活性如果使用实例化类时提供的类型参数以外的类型参数调用泛型类方法,请考虑为该方法的类型参数提供另一个标识符。