Change parameter name without breaking backwards compatibility - c#

I am working on a c# library, so we are concerned with breaking backwards compatibility, but I was wondering is it possible to change just the name of a parameter and maintain backwards compatibility because of the ability to use named parameters? An example of what I am trying to do is below
[Obsolete("use ChangeSpecificFoo(SpecificFoo specificFoo)")]
public void ChangeSpecificFoo(SpecificFoo foo)
{
_specificFoo = foo;
}
//Compile error ... already defines a member called 'ChangeSpecificFoo' with the same parameter types
public void ChangeSpecificFoo(SpecificFoo specificFoo)
{
_specificFoo = specificFoo;
}
Just changing the parameter name runs the potential risk of breaking backwards compatibility because someone could be calling the method using named parameters like ChangeSpecificFoo(foo: someSpecificFoo) , but we can't deprecate the method by adding a new method with the correct parameter name because parameter names are not included in the method signature, so the compiler sees it as a duplicate.
Is there any way around this? The only alternatives I see are changing the method name so it is not a duplicate and then deprecating the old method, or waiting until we add or remove parameters from the parameter list and changing the parameter names then(this may never happen because the method is pretty stable), or just make the change and fix any breaks that we may have from code using this library as we find them.

My first inclination for this is simple: DON'T. The name of your parameter is irrelevant outside of the method body. You're right to consider people calling it out by name, and therefore potentially breaking it. However, just changing the name of the parameter gives no real benefit.
The only possible reason for changing the name is to redefine what the method does because the old name leads to confusion. In that case, the name of the method should also be changed in order to not introduce another form of confusion. (The fact that the method signatures are identical is the first and more important reason to not change parameter names. However, this is to potentially explain why you might want to.)
If however, you are still adamant about keeping the same method signature, but altering the name, you could do this. (Again, I'm strongly recommending you either don't change it at all, or rename the method as well to continue to eliminate confusion.)
One way around this would be to have the method with both parameters, but make the second optional. Have that last parameter use the old name, and then assign it over within the method.
I would also HIGHLY recommend logging any uses of the named parameter, to see if your concern is valid about people calling it as a named parameter.
public void ChangeSpecificFoo(SpecificFoo specificFoo = null, SpecificFoo foo = null)
{
if (foo != null && specificFoo == null)
{
// Add any other details you can, especially
// to figure out who is calling this.
Log("Someone used a name parameter!!");
}
_specificFoo = specificFoo ?? foo;
}
As Dmitry Bychenko pointed out in the comments, this will not stop anyone from calling this method like so: ChangeSpecificFoo(null, new SpecificFoo()), which will trigger a logging.
His observation introduces another reason why this is a bad idea: You're now introducing ANOTHER way for people to "incorrectly" call your method. Therefore, I'll repeat my advice from the top of my answer: DON'T do this, unless you really really really need to change that parameter name.

Related

Passing a property to a method for read/write

I would like to know how to pass a property to a method.
Currently, this is my method:
public static string Pick(this IFilePicker openFileService, Func<string> getCurrentFolder, Action<string> setCurrentFolder)
I use it to pick files (with a dialog). It automatically sets the current folder of the OpenFileDialog calling the getCurrentFolder Func. If the user correctly selects a file, then, the setCurrentFolder action is called.
I'm using it like this:
Pick(openFileService, () => Settings.Current.Folder, str => Settings.Current.Folder = str);
But it looks cumbersome to me. Why use 2 parameters instead 1? I could just pass the property.
But how?
I would like to call it like this:
Pick<Settings>(openFileService, x => x.Current.Folder);
Is that even possible?
NOTE Settings.Current is a Singleton. It's autogenerated.
Unfortunately there's no clean way of doing this. The code you've got is the simplest approach, I believe.
You could change the method to accept an Expression<Func<string>> instead, then examine the expression tree to get the property... but it would be a lot of effort, be less efficient, and give you less compile-time checking. You'd still need to pass () => Settings.Current.Folder - it would only remove the need for the final parameter.
To be specific, in your case you'd need to build an expression tree that still accessed the getter for Settings.Current, but then the setter for Folder. You'd then need to compile both expression trees.
It's all feasible, but it's a lot of fiddly work. Your current approach is clunky but simple. Unless you need to do this a huge amount, I'd just accept the clunkiness.
Assuming Settings.Current doesn't change, the other option would be to pass in the name of the property, so you'd call it with:
Pick(openFileService, Settings.Current, nameof(Settings.Folder));
That would still require reflection and would be somewhat error-prone, IMO.
A property is nothing but a package of two methods, a get- and a set-method. So by providing a property within a delegate, you reference either the one or the other. Thats why you can´t read and write the properties value within the delegate.
In order to read a property you surely need some method that returns a string and expects nothing (namely a Func<string>). When you want to set a property, you´ll need something that excepts a string. but doesn´t return anything (an Action<string>).
Furthermore, let´s see how the delegate could be defined:
Pick(string file, Delegate readAndWriteDelegate)
{
// what can you do with the delegate? You don´t know if you can provide a string or if it returns one
// do I have to use this?
readAndWriteDelegate(file);
// or this?
var result = readAndWriteDelegate();
// or even this?
var result = readAndWriteDelegate(file);
// in fact I could even use this
MyClass m = readAndWriteDelegate(3);
}
I just used the existing Delegate to show there´s no way to even declare your delegate and provide its type-safety.
Leaving asside that the code above won´t even compile as we´d have to call Invoke on the Delegate, you see it´s completely unclear what your delegate actually expects and what it returns. Even if we could determine it´s some kind of a stringdelegate, it´s unclear if the delegate should return a string or expect one or even do both and thus how we can call it.
Suggested just returning the path, but actually Pick() method needs to return the file as well as setting the path.
I'd add an overload or new method to the OpenFileService which will read/set the Path in the Settings.Current object, so the calls don't have to care where the 'current' path comes from. I'm assuming that 90+ % of the time you'll always read Settings.Current.Path and Write back to Settings.Current.Path so it's probably best to make the OpenFileService handle this, rather than every call to it?

Is it possible to mirror a method?

for example, there are bunch of overloads of method:
public void MyLongFunctionName(string arg1,...) ...
public void MyLongFunctionName(int arg1,...) ...
//.... many different argument types
To make a shortcut of that long function, i used i.e. my() :
public void my(string arg1,...) ...
public void my(int arg1,...) ...
....
however, is something like this possible to make my() as a shortcut of MyLongFunctionName() , without defining bunch of my() methods (like above) ?
for example, in PHP you can copy function, like :
$my = MyLongFunctionName(arg1, arg2....);
//execute
$my(arg1, arg2....)
P.S. Note to all downvoters and duplicate-markers:
this topic is not duplicate, because that referred topic doesnt answer the question at all. It executes plain function, and even says, that it is not alias at all:
so, that topic doesnt solve the problem. instead, I want to mirror(a.k.a. ALIAS) whole overloads of specific method with i.e. my(), which can accept variation of parameters. so, please stop mindless downvotings of what you dont read.
I'm afraid what you are asking is not possible.
What you want is a kind of delegate for a whole bunch of methods. It's called a method group.
A method group is a set of overloaded methods resulting from a member lookup (§7.4).
For example something.ToString is a method group. It may contain one or more methods, depending on whether ToString has overloads for this specific class.
This is a compile time construct. You cannot put a method group into a variable, like you can with a single function. You can make a delegate from a method group, but that involves getting a specific overload and transforming only that into the delegate.

redundant 'IEnumerable.OfType<T>' call consider comparing with 'null' instead

I'm getting this message from ReSharper. ReSharper is not proposing the change that I think would be appropriate after examining the code. As a result I am concerned that the problem might might be my not understanding what's going on instead of ReSharper not being as helpful as it could be.
public interface IFrobable { }
public class DataClass
{
public List<IFrobable> Frobables {get; set;}
//...
}
public class WorkerClass
{
//...
void Frobinate(List<IFrobable> frobables)
{
//Frobs the input
}
void DoSomething(List<IFrobable> input>)
{
//Original code with Resharper on OfType<IActivity>
Frobinate(input.OfType<IFrobable>().ToList());
//Suggested change from ReSharper - Is this a generic refactor
//instead of issue specific?
Frobinate(Enumerable.OfType<IFrobable>(input).ToList());
//What I think should be safe to do - compiles and appears to work
Frobinate(input);
}
}
Is there any reason why my proposed change might not be safe.
This is a regular function call:
Enumerable.OfType<IFrobable>(input)
This is the same function but invoked as an extension method:
input.OfType<IFrobable>()
In your case:
Frobinate(input);
Is absolutely fine because:
input.OfType<IFrobable>().ToList()
Equals to:
input.Where(x => x as IFrobable != null).ToList()
And in you method input is already defined as List<IFrobable> so what's the point?
Your last case may or may not introduce a logic error.
Do you really want Frobinate the ability to modify the input list passed into DoSomething or just a copy of those references?
//Suggested change from ReSharper
Actually, invoking OfType as a static method on Enumerable rather than as an extension method on input is not a suggestion from ReSharper - it's a context action. I expound on the difference in this post.
To the actual issue:
The inspection
Redundant 'IEnumerable.OfType<T>' call. Consider comparing with 'null' instead
is not one that ReSharper offers a quick fix solution with, I guess since there isn't a single unambiguously 'correct' change to make. It's just saying
hey, everything in input is definitely going to be of type IFrobable - if you're trying to filter this list you might have meant to be filtering by nullness instead
This probably isn't relevant in your case.
As to your proposed fix - as already noted, this will mean passing the actual List<> reference given to DoSomething to Frobinate, rather than a new List<> containing the same items - if this is OK, then go for it.
in your example you have input which already consists of elements of type IFrobable so ReSharper says that it doesn't make sense to filter them by type IFrobable because the filter condition is always true it proposes you to use just input.ToList() invocation or to filter elements buy nullness: input.Where(element => element != null).ToList()

Is it necessarily bad style to ignore the return value of a method

Let's say I have a C# method public void CheckXYZ(int xyz) {
// do some operation with side effects
}
Elsewhere in the same class is another method public int GetCheckedXYZ(int xyz) {
int abc;
// functionally equivalent operation to CheckXYZ,
// with additional side effect of assigning a value to abc
return abc; // this value is calculated during the check above
}
Is it necessarily bad style to refactor this by removing the CheckXYZ method, and replacing all existing CheckXYZ() calls with GetCheckedXYZ(), ignoring the return value? The returned type isn't IDisposable in this case. Does it come down to discretion?
EDIT: After all the responses, I've expanded the example a little. (Yes, I realise it's now got out in it, it's especially for #Steven)
public void EnsureXYZ(int xyz) {
if (!cache.ContainsKey(xyz))
cache.Add(xyz, random.Next());
}
public int AlwaysGetXYZ(int xyz) {
int abc;
if (!cache.TryGetValue(xyz, out abc))
{
abc = random.Next();
cache.Add(xyz, abc);
}
return abc;
}
It entirely depends upon what that return value is telling you and if that is important to know or not. If the data returned by the method is not relevant to the code that is calling it then ignoring it is entirely valid. But if it indicates some failure/counter/influential value then ignore it at your peril.
Usually it's bad style, yes. It's allowed and ok where methods return an instance of the class for chaining (foo.bar().baz().xyz().asdf() => asdf returns the instance foo but you don't need it anymore)
In your case the point of bad style wouldn't be the ignored return value but the methods with side effects. A CheckXyz() function should always return a boolean and have no further side effects.
In general, side effects are bad and if you call a method and can ignore the returned value it means that the method/object/library/program might be poorly designed.
A common C convention is to write this:
(void)GetCheckedXYZ();
The cast to void has no effect, but by convention it shows that the developer knows that the return value is being ignored, i.e. it shows it's deliberate.
C# won't let you do that, but I've seen this instead (Also in Java):
/*(void)*/GetCheckedXYZ();
Which some may feel lacks aesthetics, but it does convey the intent of the developer without resorting to alternative versions of methods, which to my eye seems worse.
A lot of these answers have good points. I'd just add that if you choose to ignore a return value, then comment it along the lines of "don't care about the return value because...", so that the next person who comes into the code will see that you have not missed it by accident and that you have thought things through
EDIT: better still, put your comment inside an empty block
if (!something()) {
// Not worried if this fails because blah
}
IMHO it's generally best to have one (and only one) way of doing things to avoid duplicating your codebase. Generally though, if you sometimes use and sometimes don't use the return value, it's probably a sign that your code could be broken down in a better way. In your example, it would probably be fine if both of those functions called a third (common) function to avoid duplicating the core functionality.
Error codes should always be checked for and handled but if the function's just returning information then what you do with that information is up to you.
[Edit] ...and as dbemerlin points out, side effects should be avoided wherever possible.
you could work with out parameters as well.

What idiom (if any) do you prefer for naming the "this" parameter to extension methods in C#, and why?

The first parameter to a C# extension method is the instance that the extension method was called on. I have adopted an idiom, without seeing it elsewhere, of calling that variable "self". I would not be surprised at all if others are using that as well. Here's an example:
public static void Print(this string self)
{
if(self != null) Console.WriteLine(self);
}
However, I'm starting to see others name that parameter "#this", as follows:
public static void Print(this string #this)
{
if(#this != null) Console.WriteLine(#this);
}
And as a 3rd option, some prefer no idiom at all, saying that "self" and "#this" don't give any information. I think we all agree that sometimes there is a clear, meaningful name for the parameter, specific to its purpose, which is better than "self" or "#this". Some go further and say you can always come up with a more valuable name. So this is another valid point of view.
What other idioms have you seen? What idiom do you prefer, and why?
I name it fairly normally, based on the use. So "source" for the source sequence of a LINQ operator, or "argument"/"parameter" for an extension doing parameter/argument checking, etc.
I don't think it has to be particularly related to "this" or "self" - that doesn't give any extra information about the meaning of the parameter. Surely that's the most important thing.
EDIT: Even in the case where there's not a lot of obvious meaning, I'd prefer some meaning to none. What information is conferred by "self" or "#this"? Merely that it's the first parameter in an extension method - and that information is already obvious by the fact that the parameter is decorated with this. In the example case where theStringToPrint/self option is given, I'd use outputText instead - it conveys everything you need to know about the parameter, IMO.
I name the variable exactly how I would name it if it were a plain old static method. The reason being that it can still be called as a static method and you must consider that use case in your code.
The easiest way to look at this is argument validation. Consider the case where null is passed into your method. You should be doing argument checking and throwing an ArgumentNullException. If it's implemented properly you'll need to put "this" as the argument name like so.
public static void Print(this string #this) {
if ( null == #this ) {
throw new ArgumentNullException("this");
}
...
}
Now someone is coding against your library and suddenly gets an exception dialog which says "this is null". They will be most confused :)
This is a bit of a contrived example, but in general I treat extension methods no different that a plain old static method. I find it makes them easier to reason about.
I have seen obj and val used. I do not like #this. We should try to avoid using keywords. I have never seen self but I like it.
I call it 'target', since the extension method will operate on that parameter.
I believe #this should be avoided as it makes use of the most useless language-specific feature ever seen (#). In fact, anything that can cause confusion or decrease readability such as keywords appearing where they are not keywords should be avoided.
self reminds me of python but could be good for a consistent naming convention as it's clear that it's referring to the instance in use while not requiring some nasty syntactic trickery.
You could do something like this...
public static void Print(this string extended)
{
if(extended != null) Console.WriteLine(extended);
}

Categories