我看到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
的类的全局上下文呢。
我的意思是如果有人会问我,我猜应该会有错误而不是警告。
编译器为什么允许这样做? (我很乐意听到一个合理的答案)
答案 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,证明它的类型正确。