9

我看到了这个有趣的问题 ,它讨论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 所说,编译器确实会发出警告。

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

我的意思是,如果有人问我,我想那里应该有错误不是警告

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

4

2 回答 2

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 谈到了通用方法(C# 编程指南)中的灵活性和良好实践:

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

于 2013-02-26T09:29:46.857 回答
2

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

如果将 MyMethod() 更改为:

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

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

于 2013-02-26T09:29:53.040 回答