为什么泛型类型参数与其他成员之间存在名称冲突

时间:2012-10-19 10:16:59

标签: c# generics

有时会有类似的东西:

class X {
  ...
}

class Y {
  X X {
    get { ... }
    set { ... }
  }
}

因为X描述了类型是什么(作为类名),以及被访问/变异的值(作为属性名称)。到现在为止还挺好。假设你想做同样的事情,但是以通用的方式:

class Z<T> {
  T T {
    get { ... }
    set { ... }
  }
}

对于此示例,编译器会抱怨:The type 'Z<T>' already contains a definition for 'T'

对于属性,变量和方法会发生这种情况,我不太明白为什么 - 编译器确实知道T是一个类型,因此可以用与第一个示例相同的方式来计算它?

简短版本:为什么第一个示例有效,但不是第二个?

编辑:我刚刚发现,如果我“重构&gt;重命名”类型参数,例如从T到U,IDE会将其更改为:

class Z<U> {
  U T {
    get { ... }
    set { ... }
  }
}

所以那里的东西知道什么是类型,什么是成员名称

3 个答案:

答案 0 :(得分:4)

可能的答案:

当您编写非通用版本时,您可能无法控制类X的名称,并且人们可能希望您的属性被称为X,因此您可能没有选择

当您编写通用版本时,没有人真正关心您所谓的类型参数,因此您只需选择其他名称即可解决此问题。

Ergo,在编写新的通用编译器时,团队开始“我们可以让我们的编译器能够弄清楚何时他的意思是类型参数 - T”当他意味着属性 - T,但这并不是必要的,因为他可以解决它,所以让我们把时间花在更高效的事情上。“

(然后VS团队去了“该死的,编译器团队已经为此烦恼了,现在我们需要弄清楚如何让用户在发现它无法编译时重构这个”...)< / p>

答案 1 :(得分:3)

我认为另一种可能性在于错误消息:

  

“Z”类型已包含“T”的定义。

任何一种类型都可能只定义一次唯一命名的标识符(除了重载方法,因为它们也有参数)。

在第一个示例中,X(类型)是由类Y定义的;它是在外面定义的。而X(属性)是由类Y定义的

Z<T>的第二个示例中,T(类型)由类Z定义,T(属性)定义在班级Z。编译器认识到它正在为一个类创建两个相同名称的标识符,然后举起手来说:“不!不!不!”

(然后正如@Rawling指出的那样,VS IDE团队陷入了坏消息。)

答案 2 :(得分:0)

类型和名称之间存在差异。当你不知道(当时或编写代码)它被称为什么时,你会怎么写函数T?

编辑:上述答案错误地假设预期的行为是属性名称会随着T的类型而变化。