Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there a name clash between generic type parameter and other members

Tags:

c#

generics

Sometimes it's useful to have something like:

class X {
  ...
}

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

because X describes both what the type is (as a class name), and the value being accessed/mutated (as the property name). So far so good. Suppose you wanted to do the same thing, but in a generic way:

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

For this example, the compiler complains that: The type 'Z<T>' already contains a definition for 'T'.

This happens for properties, variables and methods, and I don't quite understand why - surely the compiler knows that T is a type and can therefore figure it out the same way as in the first example?

Short version: Why does the first example work, but not the second?

EDIT: I've just discovered that if I "Refactor > Rename" the type parameter, say from T to U, the IDE changes it to:

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

so something in there knows what's a type and what's a member name

like image 653
Philip C Avatar asked Oct 19 '12 10:10

Philip C


People also ask

How do you indicate that a class has a generic type parameter?

A generic type is declared by specifying a type parameter in an angle brackets after a type name, e.g. TypeName<T> where T is a type parameter.

Which one of the following options is the correct name for empty type parameter?

It is called generics.

How do I get a class instance of generic type T?

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. A solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.


2 Answers

Possible answer:

When you're writing the non-generic version, you probably can't control the name of class X, and people might expect your property to be called X, so you might not have a choice.

When you're writing the generic version, nobody really cares what you called the type parameter, so you can work around this by just choosing another name.

Ergo, when writing the new generic compiler stuff, the team went "We could make our compiler able to figure out when he means type-parameter-T and when he means property-T, but it's not really necessary as he can work around it, so let's spend our time on something more productive instead."

(And the VS team then went "Damn, the compiler team have saddled us with this, now we need to figure out how to let the user refactor this when he finds out it can't compile"...)

like image 195
Rawling Avatar answered Sep 22 '22 05:09

Rawling


Another possibility I think lay in the error message:

The type 'Z' already contains a definition for 'T'.

Any single type can possibly only define a uniquely named identifier once (overloaded methods aside as they have parameters too).

In the first example X (type) is not defined by class Y; it's defined outside. Whereas X (property) is defined by class Y.

In your second example for Z<T>, T (type) is defined by class Z and T (property) is also defined by the class Z. Compiler recognizes that it's creating two identifiers of the same name for a single class, throws its hands up and says, "Nope! Nope! Nope!"

(Then as @Rawling points out, the VS IDE team got stuck with the bad news.)

like image 45
Chris Sinclair Avatar answered Sep 23 '22 05:09

Chris Sinclair