通用类型冲突?

时间:2013-02-26 09:17:04

标签: c# .net generics type-safety

我看到this interesting question在方法层面谈论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)
            {
            }
        }

作为Eric said,编译器会发出警告。

但是,嘿,安全类型怎么了?我假设方法级别存在类型安全性,但是已经声明T的类的全局上下文呢。

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

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

2 个答案:

答案 0 :(得分: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>();
    }
}

该计划:

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";
}

没有编译错误,也不应该,因为类型安全性得以保留。程序可以编译。没有歧义。

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

MSDN在Generic Methods (C# Programming Guide)中说明了灵活性和良好做法:

  

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

答案 1 :(得分:2)

这不是类型安全问题。这只是一个可读性问题 - 这就是为什么它只是一个警告。 (另外,T隐藏外部T。)

如果将MyMethod()更改为:

public void MyMethod<T>(T k)
{
    Console.WriteLine(typeof(T).FullName);
}

它将为您的示例代码打印出System.String,证明它的类型正确。