2

I have written a small code, but found something amazing. I have a class name Students and inside that calss declared a List<> like this with variable name Students (same as the Class name)

  Class Students
{
    private String Name;
    private int Age;   
    public Students(){}

    List<Students> Students = new List<Students>();

...
}

Here compile time error is

'Students': member names can not be the same as their enclosing type

But if I declare the same List in other class ... like

        Class Students
        {
           private String Name;
           private int Age;   
           public Students(){}    
           ...
        }


        Class Program
        {
         ....
            List<Students> Students = new List<Students>();
            Students.Add(new Students("Deb","B++"));
            Students.Add(new Students("DDD", "A++"));
          ............
        }

This Works fine. My Question is, why? How we can create custom variable as the class name in other calsses but not in the same class? Any elaborate answer would be good, as I want to gain knowledge in this.

Debhere
  • 1,055
  • 2
  • 19
  • 41
  • 7
    Name your local variables with the correct casing. `List students = new List();` – Myrtle Aug 21 '12 at 07:41
  • The other way to achieve that would be the Students class hides the list, and you have a function of .Add as static which you add Students to it. – BugFinder Aug 21 '12 at 07:43
  • That's not amazing .. *properties* and *fields* cannot be named after the enclosing type. However, *local variables* will "just shadow" the name of the enclosing type. (Not that I recommend it.) –  Aug 21 '12 at 07:43
  • Note that you can introduce a _local variable_ (like in your second example) called `Students` even inside the `Students` class; it's specifically a _member_ you can't do this with. – Rawling Aug 21 '12 at 07:44
  • @Aphelion or _students, it depends on notation you choose – Konstantin Chernov Aug 21 '12 at 07:58
  • A very similar question was asked here: http://stackoverflow.com/questions/4074055/why-c-sharp-member-names-cant-be-the-same-as-the-enclosing-type-name, but the answers are not very satisfying IMO. The conclusion was that it's just a limitation of C#, since VB.NET does allow this situation to occur. – Tudor Aug 21 '12 at 08:12

6 Answers6

7

The answer is mentioned in the error message:

'Students': member names can not be the same as their enclosing type

It's only an error if you are inside the class with the same name as the member.

Anyway, it's a bad idea in any case to name variables like this. They should be not be capitalized.

Edit: Here's an example that might cause ambiguity:

class A
{
    public void Foo() { }
}

class B
{
    private A B = new A();

    static void Foo() { }

    void Bar()
    {
        B.Foo(); // what am I calling here?
    }
}

Edit 2: Searching around a bit I've found a very similar question: Why C# member names can't be the same as the enclosing type name? and the consensus was just that it's a limitation of C# (no clear explanation why). VB.NET seems to allow that this situation to occur.

Community
  • 1
  • 1
Tudor
  • 61,523
  • 12
  • 102
  • 142
  • 1
    This doesn't really answer _why_ this isn't allowed. – Rawling Aug 21 '12 at 07:46
  • 1
    Ok Fine, but where is the catch here? Is it some conflicting nature of the variable name and the class name? or is it some convention we need to follow? Anyway if i change Students - > students it will work, but my question is what actually stopping it to compile. The same is running if it is in other class. So what is the blocking point here. – Debhere Aug 21 '12 at 07:48
  • @Debhere You cant have property with same name as class name. [HERE](http://msdn.microsoft.com/en-us/library/hdhfk2xk(v=vs.90).aspx) are more details about error. – Renatas M. Aug 21 '12 at 07:54
  • 2
    @Debhere: I've posted an example that could cause problems if this type of declarations were allowed. – Tudor Aug 21 '12 at 07:58
  • 1
    @Tudor If `B` is a local variable rather than a member, the same ambiguity applies. – Rawling Aug 21 '12 at 08:01
  • @Rawling: You're right, I need to think further... I've searched around other SO questions but it appears nobody was able to give a satisfactory answer, and it seems that the same situation *is allowed* in VB.NET – Tudor Aug 21 '12 at 08:02
  • @Rawling: It seems that in the case of private variable the call is resolved to the variable method and not the static method. Maybe they preferred not to set such rules for members as well? – Tudor Aug 21 '12 at 08:05
  • Thanks I got it, why its a wrong practice. But @Rawling Asked this is also same for the local variable. – Debhere Aug 21 '12 at 08:24
  • @Debhere: I guess the only plausible answer is that they want it to conflict with the constructor name, but I really can't see a reasons for this limitation. – Tudor Aug 21 '12 at 08:26
  • @Tudor Yeah, it looks like it's just a fairly arbitrary bit of the spec. (It helps stop confusing code, so fair enough.) – Rawling Aug 21 '12 at 08:29
  • Tudor and @Rawling Thanks for your help and such a elaborate asnwers – Debhere Aug 21 '12 at 09:03
3

Your class is named Students, so obviously the only member allowed to be named same is constructor.

Konstantin Chernov
  • 1,899
  • 2
  • 21
  • 37
  • This could explain why this restriction specifically applies to members and not local variables. – Rawling Aug 21 '12 at 07:48
  • @Roger This is somewhat convincing, but ocnstructor is also a different way to represent a method. – Debhere Aug 21 '12 at 07:53
1

It would be ambiguous in the same class whether you're addressing the class or the member, whereas in another class it isn't.

Besides, you should name the class Student if it represents a single student, even though a List of Students may sound more intuitive than a List of Student. If you're holding a single reference, it looks wrong.

Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
  • 1
    It really is the ambiguity - if one writes `Students.DoSomething()`, do they mean the class or the list? – waldrumpus Aug 21 '12 at 07:45
  • Then why allow it when the ambiguity is with a local variable rather than with a member variable? – Rawling Aug 21 '12 at 07:46
  • @Rawling I do not know, since I haven't stumbled across this yet (usually locals are camel-case in my code). I *suppose* it's kept similar to the local vs. member behavior: A local variable hides a member with the same name unless you use `this`. Does anybody know...? – Matthias Meid Aug 21 '12 at 07:49
1

When you declare it with same name inside class how the compiler will determine if its a class or a variable but when you declare it in other class dot notation comes in like below.

Program.Students

and now compiler can see difference between two.

Ravi Patel
  • 2,136
  • 3
  • 32
  • 48
1

the C# language specification documentation on class members is particularly relevant for your case, it says this:


A class-declaration creates a new declaration space (Section 3.3), and the class-member-declarations immediately contained by the class-declaration introduce new members into this declaration space. The following rules apply to class-member-declarations:

•Instance constructors, destructors and static constructors must have the same name as the immediately enclosing class. All other members must have names that differ from the name of the immediately enclosing class.

•The name of a constant, field, property, event, or type must differ from the names of all other members declared in the same class.

•The name of a method must differ from the names of all other non-methods declared in the same class. In addition, the signature (Section 3.6) of a method must differ from the signatures of all other methods declared in the same class.

•The signature of an instance constructor must differ from the signatures of all other instance constructors declared in the same class.

•The signature of an indexer must differ from the signatures of all other indexers declared in the same class.

•The signature of an operator must differ from the signatures of all other operators declared in the same class.


constructors always have the same name as the class, and even if you don't specify a constructor explicitly a default constructor will exist. the constructor, being present always, has basically claimed the rights to that class-member name thus disallowing any other class-member to be named likewise (except of course for the special case of the destructor and static constructor).

PS: VB has different rules and naming for constructors, which is why the above does not apply there.

Community
  • 1
  • 1
mtijn
  • 3,610
  • 2
  • 33
  • 55
1

How we can create custom variable as the class name in other calsses but not in the same class?

This is not the case. You are doing two different things in your code examples. In your first example, you are naming a member of a type with the name of the enclosing type. In the second case, you are naming a variable with the type name used as a generic type parameter. There is no inconsistency, they are completely different things.

Actually, you are able to name variables the same as their enclosing type. You just can not name members the same as their enclosing type.

public class Students
{
     public Students()
     {
        Students Students = new Students(); //bad idea, but it compiles
    }
}

If you really need this behavior, you can do this:

    public class StudentsBase
    {
         public List<Students> Students;
    }

    public class Students : StudentsBase
    {
        public Students() 
        {
            Students = new List<Students>();
            Students.Add(new Students());
            Students.Add(new Students());              
        }
    }

As for the "why", I am not able to answer that.

Jason
  • 1,385
  • 9
  • 11
  • In the second case, I don't think he was concerned with the fact he could call a `List`, specifically, `Students`, more the fact he could call _anything_ `Students` even though `Students` was in use as a class name. – Rawling Aug 21 '12 at 09:00