peterdrake,
@peterdrake@qoto.org avatar

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.

#GameDev #unity #unity3d #csharp

entitledgame,

@peterdrake gogo godot? ;)

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@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
}

peterdrake,
@peterdrake@qoto.org avatar

@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.

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@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.

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@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)

peterdrake,
@peterdrake@qoto.org avatar

@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".

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@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.

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@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 or similar that it needs to get passed to - sorry about the confusion).

That's what happens when you're writing outside the IDE. ;-)

TimPurdum,

@SmartmanApps @peterdrake If we're talking C# convention, then all the public variables should be auto-properties "public string MyProp { get; set; }". Using capitalization and/or underscores to allow a user to quickly see what is private vs. public makes perfect sense to me. Also, if you like "this.MyProp", you can still use that in C#, go for it. It is valid syntax.

peterdrake,
@peterdrake@qoto.org avatar

@TimPurdum @SmartmanApps

--
Using capitalization and/or underscores to allow a user to quickly see what is private vs. public makes perfect sense to me.

That might be true if there were capitalization standards that were consistently followed even by standard libraries.

UnityEngine.Random.value -- oh, value must be a private static field, right? (Or would that be called _value?) Nope, it's a public property. (One part of the Unity documentation gives its declaration as "public static float value;", but elsewhere it's described as a property.) For added fun, it yields a different value each time it's accessed. I don't know why it's not a method.

string -- a local variable? A primitive type like int? Nope, it's a class name.

This is the source of my confusion and frustration.

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@peterdrake @TimPurdum
Yeah, in that case it's Unity who aren't following the C# conventions. The thing that frustrates me a bit is C# is Pascal for public, but in JSON they use lower (so you have to add JSON attributes). It'd be good to be consistent across the whole industry, but that's not gonna happen unfortunately...

TimPurdum,

@SmartmanApps @peterdrake this is correct. Unity is the main divergence from the community, I believe. I'm sure there's an historical reason for that.

khalidabuhakmeh,
@khalidabuhakmeh@mastodon.social avatar

@TimPurdum @SmartmanApps @peterdrake Unity folks think of C# as a means to an end, that's why they refer to code as scripts.

Also, a lot of the idioms come from C++ game development.

They're definitely unique in their approaches.

TimPurdum,

@khalidabuhakmeh @SmartmanApps @peterdrake yeah, don't they also support that other "script" language? 👀

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@TimPurdum @khalidabuhakmeh @peterdrake
😂
There was a post (tweet?) ages ago from a headhunter who thought Java was just short for JavaScript and they were the same thing. I said "if you know C then just apply for it and tell them C is short for javasCript" 😂

TimPurdum,

@SmartmanApps @khalidabuhakmeh @peterdrake recruiters rarely understand the tech they are hiring for. "Do you know .NET?" "Yes, I have been working on .NET Core." "...but what about .NET?"

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@TimPurdum @khalidabuhakmeh @peterdrake
Yeah exactly - that was the point being made at the time by the person who posted it. You have "tech" recruiters who know as much about tech as Musk does! 😂

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@TimPurdum @khalidabuhakmeh @peterdrake
Recruiter: do you know c hash?

peterdrake,
@peterdrake@qoto.org avatar

@TimPurdum @khalidabuhakmeh @SmartmanApps Unity used to support a couple of other languages (a flavor of JavaScript and something called Boo), but now it's just C#.

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@khalidabuhakmeh @TimPurdum @peterdrake
"they refer to code as scripts"
Ugh! I had someone who kept referring to a "macro", but no he wasn't talking about something in Excel (or similar). EVENTUALLY I worked out he was actually talking about an app! "Aren't apps only on phones?". No, apps existed before smartphones - a smartphone is basically a mini-computer (with phone functionality built in). He still kept calling it a macro though 🙄

peterdrake,
@peterdrake@qoto.org avatar

@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.)

SmartmanApps,
@SmartmanApps@dotnet.social avatar

@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).

peterdrake,
@peterdrake@qoto.org avatar

People generally seem to agree that C# class names should be PascalCase.

Except for, y'know, the class you'll probably use most often: string.

TimPurdum,

@peterdrake "String" is the class name, "string" is a convenience alias, same with "int", "double", etc.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#string-vs-systemstring

  • All
  • Subscribed
  • Moderated
  • Favorites
  • gamedev
  • ngwrru68w68
  • rosin
  • GTA5RPClips
  • osvaldo12
  • love
  • Youngstown
  • slotface
  • khanakhh
  • everett
  • kavyap
  • mdbf
  • DreamBathrooms
  • thenastyranch
  • magazineikmin
  • megavids
  • InstantRegret
  • normalnudes
  • tacticalgear
  • cubers
  • ethstaker
  • modclub
  • cisconetworking
  • Durango
  • anitta
  • Leos
  • tester
  • provamag3
  • JUstTest
  • All magazines