[Proposal] Allow members to have the same name as their enclosing type #2511
Replies: 8 comments 60 replies
-
This seems like a very edge-case usecase and more likely to cause maintainability issues than it is to solve. Is there any reason you can't just rename the class or method? Using your example, a |
Beta Was this translation helpful? Give feedback.
-
@FiniteReality firstly, the old library uses reflection to lookup the class 'Load' and then the void 'Load()' in that class, it cannot be changed for various reasons. Secondly, I don't think it would be that hard to change as you only have to change the test that says it cannot be named the same as the enclosing type. Public Class Class1
Public Sub Class1()
Console.WriteLine("Message1")
End Sub
End Class and in C# (referencing VB.NET) Class1 c = new Class1();
c.Class1(); will compile and produce the output as expected. |
Beta Was this translation helpful? Give feedback.
-
It isn't clear to me that even public class ClassName
{
public ClassName() { }
public void ClassName() { }
} ...is ambiguous. The signatures are different. The intent is clear. It's appropriate and desirable to have a warning, since it isn't good practice, or even keep it as an error but allow it to be downgraded to just a warning instead of making it fatal. |
Beta Was this translation helpful? Give feedback.
-
From my experience, it's unusual, but far from a proper edge case to want a member with the same name as the type. Most recently, I wanted to create the type public sealed class Type<T>
{
private Type() { }
public static Type<T> Type { get; } = new Type<T>();
} In this situation, So I for one would love to see this restriction removed. But sadly I don't think this would ever happen. There's a mistaken belief that this is bad practice (and it doesn't help the blood pressure that those that assert it's bad practice undermine that assertion by defending genuine bad practices like using This one is likely stuck on -100 points for all time and we just have to live with it, which is occasionally annoying but not really that hard to do. |
Beta Was this translation helpful? Give feedback.
-
I'm going to try a different approach. Never mind the existing code generator or inconsistency between VB.NET and C# or how keywords can be used as member names with an @ prefix. Instead, let's talk about programmers new to C#. They name things as best they can and they hit this unexpected error about naming. It doesn't make sense to them. If they're familiar with other languages, they might wonder why there is any issue with naming a member the same as the type. They may do some googling and discover that it isn't even a CLR/.NET restriction but is exclusive to C#. They may even find this discussion. Ultimately, though, it's like having one stair in a staircase that is just a little bit taller than the others. It trips you up. It's unexpected. It makes no sense. Sure, you learn to watch your step on the staircase to handle that one special case, but it's just a little more friction, a little more frustration, with what is an otherwise pleasant language to use. Worse, there doesn't seem to be any benefit to keeping the restriction (and I retract saying it isn't good practice; I don't think that's defensible). Why wouldn't we want to streamline the language with this one simple improvement? |
Beta Was this translation helpful? Give feedback.
-
I already have a code analyzer in place that reports constructor methods as their type name. class Foo {
public Foo() { }
} Will report method 'Foo()' within type 'Foo'. down the line, this pattern is recognized. Implementing this proposal would break this analyzer and probably a whole lot more as this restriction has been in place since day 1. |
Beta Was this translation helpful? Give feedback.
-
@hamarb123 The issue you are having can probably be solved with https://github.com/Fody/Fody |
Beta Was this translation helpful? Give feedback.
-
Chipping in a little..... It does seem odd that this is a restriction in C# despite being possible in IL. I wonder what the original reason was for doing it (other than avoiding confusion)? Where I just came up against it makes it more annoying (in my opinion). I'm creating a razor component in aspnet core. This component is for a Basket (so the file is named Basket.razor) and I pass in the data using a [Parameter] also called Basket (as that makes sense). Except I can't, because the class that is generated for my razor component is called Basket. So, now I have to name my parameter something else ("BasketData" ??) even though I wouldn't expect this. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Currently, the following code is not possible:
This is because the compiler doesn't allow you to have a member with the same name as the enclosing type, because that is how the constructor is declared in C#
public ClassName() { ConstructorCodeHere() }
There is a similar problem in VB.NET, which is the
New()
method (VB.NET constructor), for example:declares a class named
ClassName
, with a constructor that takes 0 arguments.Note: members named
ClassName
are allowed inClassName
in VB.NET (but not C#)But VB.NET has a solution for naming things with keywords, such as
Object
orInteger
, which is to enclose the name in square brackets [], for example:is not allowed, as
Integer
is a keyword, butis allowed, and will compile into a
void
namedInteger
(without the square brackets), and can be accessed in C# as simplyInteger
, as it is not a keyword in C#.In C#, there is a similar pattern, which is to add a @ character to the start of the member name, for example:
is not allowed, whereas
is allowed and will compile into
string
instead of@string
, as the @ symbol simply informs the compiler to not treat it as a keyword.The difference of this pattern between VB.NET and C# is that in VB.NET, the following is completely legal:
and will compile as expected, whereas in C#, the following is not legal:
and the compiler simply complains saying "error CS0542: 'ClassName': member names cannot be the same as their enclosing type".
Using the @ symbol removes the ambiguity, so it should be allowed (but probably optional).
The C# language specification should allow this, if the member has an @ symbol at the start, it should be compiled without the @ symbol (just like everything else that starts with one).
The example above should be callable like so:
which is the same usage as calling other @ members.
Note, I believe that
would actually work as well today if the type was declared in VB.NET.
The reason I specifically want this is because I have old code that requires libraries to have a
Load()
method in aLoad
class, if the method and class are not named exactly this, it will not work, so currently I am limited to 2 options: a VB.NET wrapper OR VB.NET code only. I would like to write this library completely in C#, and this is how it can be done. I'm sure there would also be other applications for this.Beta Was this translation helpful? Give feedback.
All reactions