43

I see questions similar to this with regards to parameter names that match properties on the class, but I can't find anything regarding using a parameter name that is the same as the parameter type name except for casing in C#. It doesn't seem to be a violation that I can find, but is it considered bad practice? For example, I have the following method

public Range PadRange(Range range) {}

This method takes a range, and returns a new range that has had some padding applied. So, given the generic context, I can't think of a more descriptive name for the parameter. However, I'm reminded of a a tip I picked up when reading Code Complete about "psychological distance". It says

Psychological distance can be defined as the ease in which two items can be differentiated...As you debug, be ready for the problems caused by insufficient psychological distance between similar variable names and between similar routine names. As you construct code, choose names with large differences so that you can avoid the problem.

My method signature has a lot of "Range" going on, so it feels like it may be an issue with regards to this psychological distance. Now, I see many developers do the following

public Range PadRange(Range myRange) {}

I personally have a strong distaste for this convention. Adding a "my" prefix to variable names provides no additional context.

I also see the following

public Range PadRange(Range rangeToPad) {}

I like this better than the "my" prefixing, but still don't care for it overall. It just feels overly verbose to me, and reads awkwardly as a variable name. To me, it's understood that range will be padded because of the method name.

So with all this laid out, my gut is to go with the first signature. To me, it's clean. No need to force context when it's not needed. But am I doing myself or future developers a disservice with this convention? Am I violating a best practice?

7 Answers7

100

Don't overthink this, Range range is fine. I use such kind of naming for more than 15 years in C#, and probably much longer in C++, and have never experienced any real drawbacks from it, quite the opposite.

Of course, when you have different local variables in the same scope, all of the same type, it will probably help to invest some mental effort to distinguish them properly.

Doc Brown
  • 218,378
16

I do this all the time, it is giving me great piece of mind. If it is an argument passed to a constructor that needs to be assigned to a member, my member would be named range as well and the assignment would be

this.range = range;

And I would typically have a property named Range.

They are all the same thing, only differing in context so it makes sense to maintain a single name and you will have to remember only one name. It is one thing, the differences are purely technical.

You should be strict with fully qualifying members with "this." though, but that is what StyleCop is for.

StyleCop side note

Controversy guaranteed!

To those advocating against the use of "this.": I have seen _, m, m_ and just nothing. The language itself is offering us a perfectly clear, unambiguous universally recognizable way of indicating we are dealing with a class member. Why on earth would you want to make up your own way that mutilates already perfect names?

The only reason I can think of it that it is a legacy habit from the C era, when it actually made sense to do it because there was no other way.

"It is more characters!" Seriously? "Compile time will skyrocket!" Seriously? "I will have to lift my pinky when typing it!". As if typing time had any significance in the total development time.

I recognize that any style different from what you are used to will raise some opposition. But using this consistently is hard to argue with. Here's how it works for me: Before I push a new code file I run StyleCop and it will find a number of members lacking "this" qualifiers. I put "this." on the clipboard, run by the members and insert. No effort at all.

StyleCop does a lot more than this (haha). There are so many ways a developer can (only considering code formatting) frustrate the maintenance work of his successor. StyleCop prevents most of them. It is invaluable.

If you are new to it: it typically makes you grumble for a week or two and then you will love it.

Martin Maat
  • 18,652
9

My self-guidance on naming methods, parameters and variables is pretty simple:

  1. If the name contains the type that is being passed in or returned, you're doing it wrong.
  2. Name things by what they are intended for, not what they are.
  3. Always remember that code is read more than it is written.

Thus the optimal method signature, in my opinion, would be:

Range Pad(Range toPad)

Shortening the method name is self-explanatory.

The parameter name toPad immediately tells the reader that that parameter is probably going to be modified in-place by being padded, then returned. In contrast, no assumptions can be made about a variable named range.

Further, in the actual body of the method, any other Range variables that are introduced would (should) be named by their intent, so you might have padded and unpadded... toPad conforms to those naming conventions, but range just sticks out and doesn't gel.

Ian Kemp
  • 399
3

For naming of code elements (types, variables, functions, anything), the key question to ask yourself is

If I make a typo, will the compiler find it for me?

The worst kind of typo-based bug is one where the code compiles and runs, but gives different behaviour from what you expect, for reasons which are subtle. And since it's due to a typo, it's usually very hard to see when you're inspecting the code. If a typo will stop the code compiling, then the compiler will flag up the line causing the problem, and you can easily find and fix it.

For your situation where the type and variable differ only in capitalisation, this will always be the case. (Or nearly always - with sufficient effort, I'm sure you could make it work, but you'd have to really try.) So I think you're OK there.

Where you would need to be concerned would be if there were two variables, methods, functions or properties in current scope called range and Range. In that case the compiler probably will let it through, and you're going to get unexpected behaviour at run-time. Note that that's two of any of those types of code element, not just "two variables" or "two functions" - all of those can be implicitly cast to each other, with resulting carnage when it runs. You might get warnings, but you can't guarantee anything more than that. You have similar issues if you had two types declared called range and Range.

Also note the same applies to the Hungarian notation style, where names are prefixed with one or more characters to say something more about whatever it is. If you have a variable called Range and a pointer to it called PRange, it's easy to accidentally miss the P, for example. C# should catch this, but C and C++ will only give you a warning at most. Or more worryingly, suppose you have an double version called DRange and you downsample that to a float version called FRange. Use the float one by accident (which is easy since the keys are adjacent on a keyboard) and your code will kind of work, but it'll fall over in strange and unpredictable ways when the process runs out of resolution and underflows.

We're no longer in the days where we had naming limits of 8 characters, or 16 characters, or whatever arbitrary limit. I've sometimes heard novices complaining about longer variable names making coding take longer. It's only ever novices who complain about this though. Serious coders know that what really takes time is figuring out obscure bugs - and bad choice of naming is a classic way to drop yourself in that particular hole.

Graham
  • 2,062
1

One anecdote I would like to add, while Range range this is syntactically legal, it could make things more challenging to debug or refactor. Looking for that one variable named "range" in a file with lots of variables of type Range? You may end up doing more work later as a result of this naming choice.

This is largely context-dependent though. If it is a 30 line file, my statements don't really come into play.

Jacob M.
  • 119
1

I think you can use Range range nowdays for one reason: syntax highlighting. Modern IDEs usually highlight the type names and the parameter names in different colors. Also a type and a variable have a considerable "logical distance" not to be easily confused.

If this wouldn't be the case I would consider a different name or trying to enable a plugin/extension that can do this syntax highlighting.

akaltar
  • 117
  • 3
0

When a function is generic, it stands to reason that the parameters will be generic, and thus should have generic names.

Not what you're saying, but I've seen functions that perform a generic function that have parameter names that are misleadingly specific. Like

public String removeNonDigits(String phoneNumber)

The function name sounds very generic, like this could be applied to many strings in many situations. But the parameter name is oddly specific, making me wonder if the function name is misleading, or ... what?

So sure, instead of saying Range range, you could say Range rangeToPad. But what information does this add? Of course it's the range to pad. What else would it be?

Adding some arbitrary prefix, "my" or "m_" or whatever, conveys zero additional information to the reader. When I've used languages where the compiler does not allow a variable name to be the same as a type name -- with or without case sensitivity -- I've sometimes put on a prefix or a suffix, just to get it to compile. But that's just to satisfy the compiler. One could argue that even if the compiler can distinguish, this makes it easier for a human reader to distinguish. But wow, in Java I've written statements like "Customer customer = new Customer();" a billion times and I never found it confusing. (I've always found it a bit redundant and I rather like that in VB you can just say "dim customer as new Customer" and you don't have to give the class name twice.)

Where I DO object strongly to generic names is when there are two or more instances of the same type in the same function. ESPECIALLY parameters. Like:

public Range pad(Range range1, Range range2)

What's the difference between range1 and range2? How am I supposed to know? If it's something where they truly are two generic and interchangeable values, okay, like

public boolean overlap(Range range1, Range range2)

I'd expect that to return true if the ranges overlap and false if they don't, so they are generic and interchangeable.

But if they're different, give me a clue how they are different! I was just working on a program recently that had a "Place" class to hold data about geographical places, and with variables of this type named "p", "place", "place2", "myPlace", etc. Wow, those names really help me determine which is which.

Jay
  • 2,687