8

I have 2 scenarios.

This fails:

class F<X>
{
  public X X { get; set; }
}

error CS0102: The type 'F<X>' already contains a definition for 'X'

This works:

class F<X>
{
  class G
  {
    public X X { get; set; }
  }
}

The only logical explanation is that in the second snippet the type parameter X is out of scope, which is not true...

Why should a type parameter affect my definitions in a type?

IMO, for consistency, either both should work or neither should work.

Any other ideas?

PS: I call it 'lexical', but it is probably not the correct term.

Update:

As per Henk's answer, here is a non-generic version displaying the same behavior, but perhaps easier to grok.

Fails:

class F
{
  class X { }
  public X X { get; set; }
}

Works:

class X { }
class F
{
  public X X { get; set; }
}

From what I can see, the C# compiler creates a lexical scope at type definition boundries.

It also implies that types and member names live in the same 'location' (or namespace in terms of LISP).

leppie
  • 115,091
  • 17
  • 196
  • 297
  • I dont see why the first shouldnt work, anyone able to reproduce the compiler error? – almog.ori May 13 '10 at 08:46
  • According to your update, it looks like Marcelo answered your question - he demonstrated the same thing. – Kobi May 13 '10 at 09:13
  • @Kobi: No, not quite :) I didn't downvote him either, as it is partially applicable. – leppie May 13 '10 at 10:17
  • not related, but can you check out my question leppie? http://stackoverflow.com/questions/4444708/start-a-new-project-in-xacc-ide – Isaiah Dec 14 '10 at 23:57

2 Answers2

3

The class G introduces a distinctive naming scope. If you omit the default rules, the 2 versions become:

public F<X>.X F<X>.X { get; set; }    // error
public F<X>.X F<X>.G.X { get; set; }  // OK
H H
  • 263,252
  • 30
  • 330
  • 514
  • Thanks, that seems to make a little sense :) And why: class F { class X { } public X X { get; set; } } also fails. – leppie May 13 '10 at 09:06
2

X is defined as a type in the scope of F. It is similar to this:

class F
{
  public void X();

  public int X(); // Bad, trying to redefine X.

  class G
  {
    public string X(); // OK, different scope
  }
}

F.X isn't out of scope in G, but this doesn't stop G from defining a new X.

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365