Capitalization in C# / Unity is an infuriating minefield.

Microsoft and Unity offer slightly different standards and then don't consistently follow them.

There is no entry for "capitalization" in the index for the 1000-page C# 10 in a Nutshell. There is some advice under "identifiers", but it differs from what is given by the previous two sources.

Many sources want to capitalize private and public fields differently. Why would you do that?!

Unity adds spaces and changes the capitalization when displaying class and field names.

If you refactor a name, Unity bloats your code with a FormerlySerializedAs attribute.

@peterdrake
"Many sources want to capitalize private and public fields differently. Why would you do that?!"
To use the same name and indicate scope...

Ithing MyI;
classconstructor(Ithing myi)
{
MyI=myi;
}
//myi out of scope
MyMethod(Ithing MyI)
{
//do stuff with MyI
}

@SmartmanApps

Directly addressing your point, I liked Java's answer much better:

this.x = x;

My students get confused about even that. X = x seems like a recipe for disaster.

Worse, one version of the C# convention would make both private fields and method arguments camel case, which would prevent you from doing this very thing.

Even worse, if you change your mind about the visibility of a field, you're supposed to rename it! (Bonus pain if you believe private fields should start with underscores.)

There's only one field in your example: MyI. C# makes it private by default, right? The convention would be for it to be camel, not Pascal, right?

Why is the argument to classconstructor all lower but the argument to MyMethod Pascal?

I assume classconstructor should be ClassName.

In MyMethod, the argument MyI shadows the field with exactly the same name, so you'd have to resort to the this.MyI trick anyway if you wanted to access the field.

Building the scope into the name seems like a terrible idea. I see many downsides and no benefit.

@peterdrake
"this.x=x" - that's another way to do it.

"private fields should start with underscores" - makes using Intellisense a whole bunch easier

"Why is the argument to classconstructor all lower" - as per comments, it only has scope within the constructor

"classconstructor should be ClassName" - I didn't include a class name anywhere in the example, so was just saying this is the constructor for it

"so you'd have to resort to the this.MyI" - no, you don't. That's the point.

@peterdrake
In other words, MyI and myi to us as humans are the "same name", but with different case, but the compiler knows the difference between MyI and myi (they're NOT the same name) and eliminates the need to use "this" on things, you can just use the correct case for the scope you're in (or underscore where you've used that)

@SmartmanApps I'm not talking about different scopes but about different access levels. The convention in question would want you to declare

public int X;

but

private int x;

Both are fields with the same scope, but the latter can only be accessed within this class.

--
"Why is the argument to classconstructor all lower" - as per comments, it only has scope within the constructor
--

Yes, I get that, but by the same logic shouldn't the argument to MyMethod be myi instead of MyI?

As written, the MyMethod argument MyI shadows the field MyI, so there's no way within MyMethod to refer to the field without using "this".

@peterdrake
"I'm not talking about different scopes but about different access levels" - yes, but same logic. Pascal Public, lower local (private).

"the MyMethod argument MyI shadows the field MyI" - they're the same thing! I'm passing MyI, which has scope throughout the whole class, to the method, and it gets used directly within the method with no need to use "this". There's NO "this.MyI=MyI" in the method(!), you just call MyI - it's in scope everywhere, having been declared at the top.

@peterdrake
In fact, that's my mistake. MyI doesn't need to get passed to the method - that's probably where the confusion came from. You can just call the method without passing MyI to it - it's already in scope (I'm just used to writing it that way cos often I have a base constructor it needs to get passed to - sorry about the confusion).

@SmartmanApps Ah, yes, that does explain that confusion.

I'm still wondering about this:

If the field is private (as almost all fields should be), then it should be called myi, right?

If so, that field and the argument to the constructor have exactly the same name. You'd need:

private IThing myi;
MyClass(IThing myi)
{
this.myi = myi;
}

You could do it with a leading underscore:

private IThing _myi;
MyClass(IThing myi)
{
_myi = myi;
}

In any case, having two different variables that differ by one character (either an underscore or initial capitalization) strikes me as a bad idea. A trivial typo could easily lead to a syntactically correct program that does something different from what was intended.

(Mind you, many years of Java made me perfectly happy with

Thing thing = new Thing();

but there Thing is a class and thing is an instance.)

@peterdrake
Yes, but in my example I was declaring it as Public, to highlight I use Pascal for Public. Yes, you can use lower-case for private, but as I alluded to I prefer underscore for backing fields (in my example I was just illustrating passing an interface, which is where I most use case-sensitivity) - makes it easier with Intellisense (if neither has an underscore, then the first Intellisense suggestion will always include both spellings - (no) underscore narrows it down right away).

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.