Is this the right way to overload a method? - c#

I am working on my own command line arguments parser and after reading dozens of articles regarding method overloading I am still not certain if I am doing it right.
Am I getting any benefit from overloading methods this way? I know I could just write the entire thing in a single method (with default value parameters) by branching, but I'm experimenting overloads at the moment and I would like to know whether to continue on this path or not.
public static class MyParsers
{
private static List<string> args;
static MyParsers()
{
args = Environment.GetCommandLineArgs().ToList();
}
public static List<string> ParseOptions()
{
return ParseOptions(false);
}
public static List<string> ParseOptions(bool toLowercase)
{
// DEBUG: Change command line arguments here.
var arguments = args;
return !toLowercase
? arguments
: arguments.MyExtToLower();
}
public static bool OptionExists(string option)
{
return OptionExists(option, false);
}
public static bool OptionExists(string option, bool toLowercase)
{
var list = ParseOptions(toLowercase);
for (var i = 1; i < list.Count; i++)
{
if (list[i].StartsWith(option)) return true;
}
return false;
}
}

Yes that is the correct way to use overloads.
One thing to note about default parameters.
If you have two assemblies, A and B, A calls the function in B.
If you change the default in B:
using default values for parameters you need to recompile both assembly A and B for this change to take effect
using overloads you only need to recompile B.
This is because for default parameters, at compile time the compiler inserts the default values.

Yes, that's fine.
As you already know, you could also use optional parameters with default values, if your overloads only call another method with a default value (this would reduce the number of line of code).

Yep, this is how overloads work.
But a side-node:
Do you need your code to be used from languages which don't support
optional parameters? If so, consider including the overloads.
Do you have any members on your team who violently oppose optional parameters? (Sometimes it's easier to live with a decision
you don't like than to argue the case.)
Are you confident that your defaults won't change between builds of your code, or if they might, will your callers be okay with that?
Source: Should you declare methods using overloads or optional parameters in C# 4.0?

The "problem" with optional parameters is that if the default value is changed in some future version X of your assembly A then any client assemblies C that reference A will need to be recompiled in order to "see" the change -- loading an updated version of A will cause them to call the new methods with the old default values.
If this is not a potential problem then using optional parameters is more convenient. The equivalent version that emulates optional parameters using multiple overloads does not have this issue because in that case the default value is baked into assembly A instead of into C.

I think your style of overloading is fine.
If you thought you might have loads of different parsing arguments (ToUpperCase etc)
rather than have one class with lots of overloaded methods you might consider using object inheritance and have a LowerCaseParser, CamelCaseParser etc...

Related

How to use existing method instead of lambda when it's not static?

This must be a duplicate but i haven't found it. I've found this question which is related since it answers why it's recommended to use a method group instead of a lambda.
But how do i use an existing method group instead of a lambda if the method is not in the current class and the method is not static?
Say i have a list of ints which i want to convert to strings, i can use List.ConvertAll, but i need to pass a Converter<int, string> to it:
List<int> ints = new List<int> { 1 };
List<string> strings = ints.ConvertAll<string>(i => i.ToString());
This works, but it creates an unnecessary anonymous method with the lambda. So if Int32.ToString would be static and would take an int i could write:
List<string> strings = ints.ConvertAll<string>(Int32.ToString);
But that doesn't compile - of course. So how can i use a method group anyway?
If i'd create an instance method like this
string FooInt(int foo)
{
return foo.ToString();
}
i could use strings = ints.ConvertAll<string>(FooInt);, but that is not what i want. I don't want to create a new method just to be able to use an existing.
There is an static method in the framework, that can be used to convert any integrated data type into a string, namely Convert.ToString:
List<int> ints = new List<int> { 1 };
List<string> strings = ints.ConvertAll<string>(Convert.ToString);
Since the signature of Convert.ToString is also known, you can even eliminate the explicit target type parameter:
var strings = ints.ConvertAll(Convert.ToString);
This works. However, I'd also prefer the lambda-expression, even if ReSharper tells you something different. ReSharper sometimes optimizes too much imho. It prevents developers from thinking about their code, especially in the aspect of readability.
Update
Based on Tim's comment, I will try to explain the difference between lambda and static method group calls in this particular case. Therefor, I first took a look into the mscorlib disassembly to figure out, how int-to-string conversion exactly works. The Int32.ToString method calls an external method within the Number-class of the System namespace:
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), SecuritySafeCritical]
public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(this, null, NumberFormatInfo.GetInstance(provider));
}
The static Convert.ToString member does nothing else than calling ToString on the parameter:
[__DynamicallyInvokable]
public static string ToString(int value)
{
return value.ToString(CultureInfo.CurrentCulture);
}
Technically there would be no difference, if you'd write your own static member or extension, like you did in your question. So what's the difference between those two lines?
ints.ConvertAll<string>(i => i.ToString());
ints.ConvertAll(Convert.ToString);
Also - technically - there is no difference. The first example create's an anonymous method, that returns a string and accepts an integer. Using the integer's instance, it calls it's member ToString. The second one does the same, with the exception that the method is not anonymous, but an integrated member of the framework.
The only difference is that the second line is shorter and saves the compiler a few operations.
But why can't you call the non-static ToString directly?
Let's take a look into the ConvertAll-method of List:
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
{
if (converter == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
}
List<TOutput> list = new List<TOutput>(this._size);
for (int i = 0; i < this._size; i++)
{
list._items[i] = converter(this._items[i]);
}
list._size = this._size;
return list;
}
The list iteraterates over each item, calls the converter with the item as an argument and copys the result into a new list which it returns in the end.
So the only relation here is your converter that get's called explicitly. If you could pass Int32.ToString to the method, the compiler would have to decide to call this._items[i].ToString() within the loop. In this specific case it would work, but that's "too much intelligence" for the compiler. The type system does not support such code conversions. Instead the converter is an object, describing a method that can be called from the scope of the callee. Either this is an existing static method, like Convert.ToString, or an anonymous expression, like your lambda.
What causes the differences in your benchmark results?
That's hard to guess. I can imagine two factors:
Evaluating lambdas may result in runtime-overhead.
Framework calls may be optimized.
The last point especially means, that the JITer is able to inline the call which results in a better performance. However, those are just assumptions of mine. If anyone could clarify this, I'd appreciate it! :)
You hit the nail on the head yourself:
This works, but it creates an unnecessary anonymous method with the
lambda.
You can't do what you're asking for because there is no appropriate method group that you can use so the anonymous method is necessary. It works in that other case because the implicit range variable is passed to the delegate created by the method group. In your case, you need the method to be called on the range variable. It's a completely different scenario.

Is there a benefit to using the c# out/ref keyword to "return" > 1 item in a method, instead of an object

Returning multiple things from a method, involves either:
returning an object with properties OR
using the out keyword to simply modify incoming parameters
Is there a benefit to using one system or the other? I have been using objects, but just discovered the out keyword, so wondering if I should bother refactoring.
You shouldn't bother refactoring just to utilize out parameters. Returning a class or struct would be preferred as long as structure is reusable.
A common use for out parameters which I would suggest using is to return a status for a call with that is possible to fail. An example being int.TryParse.
It has the possibility of failing, so returning a bool makes it easy to determing whether or not you should use the out parameter.
Another possible solution to returning multiple values from a method would be to use a Tuple. They can return n number of results. E.g.
public Tuple<bool, bool, string> MyMethod()
{
return new Tuple<bool, bool, string>(false, true, "yep");
}
In general, if the object that you are returning is not used anywhere else outside of the return value of your method or a group of similar methods, it is a good indication that you should refactor. When you need to create a special class simply to be used as a return value of a method, it means that you are working around C#'s inability to return multiple values from a method, so the out keyword may be a very good option for you.
On the other hand, if you use the multi-part return value in other places, such as storing them in collections or passing as arguments to other methods, there's probably no need to refactor, because the return object is meaningful.
Compare these two methods:
interface DictionaryReturn<T> {
T Value {get;}
bool Success {get;}
}
...
class Dictionary<K,V> {
...
public DictionaryReturn<V> TryGetValue(K key) {
...
}
}
or
class Dictionary<K,V> {
...
public bool TryGetValue(K key, out V res) {
...
}
}
The first case introduces a special DictionaryReturn<T> class that provides the value and an indicator that the value was found in the dictionary. There is rarely, if ever, a reason to store or use DictionaryReturn<T> objects outside the call to TryGetValue, so the second option is better. Not surprisingly, it is the second option that the designers of the .NET collections library have implemented.
I prefer to use Object with properties. If you use out keyword, you need to define it in other line. It is not as clear as return Object;
The reason to use out keyword is to ensure that code inside the method always sets a value to the out parameter. It's a compile time check that what you intended to do in the function, you did do.

What is 'this' used for in C# language?

I've read open source c# code and there is a lot of strange grammar (to me).
They declare method arguments with the this keyword like this:
this object #object
What does it mean?
If I remove 'this' keyword where is before the data type, then will it work differently?
Sounds like an Extension Method.
The # symbol allows the variable name to be the same as a C# keyword - I tend to avoid them like the plague personally.
If you remove the this keyword, it will no longer be an extension method, just a static method. Depending on the calling code syntax, it may no longer compile, for example:
public static class IntegerMethods
{
public static int Add(this int i, int value)
{
return i + value;
}
}
int i = 0;
// This is an "extension method" call, and will only compile against extension methods.
i = i.Add(2);
// This is a standard static method call.
i = IntegerMethods.Add(i, 2);
The compiler will simply translate all "extension method calls" into standard static method calls at any rate, but extension method calls will still only work against valid extension methods as per the this type name syntax.
Some guidelines
These are my own, but I find they are useful.
Discoverability of extension methods can be a problem, so be mindful of the namespace you choose to contain them in. We have very useful stuff under .NET namespaces such as System.Collections or whatever. Less useful but otherwise "common" stuff tends to go under Extensions.<namespace of extended type> such that discoverability is at least consistent via convention.
Try not to extend often used types in broad scope, you don't want MyFabulousExtensionMethod appearing on object throughout your app. If you need to, either constrain the scope (namespace) to be very specific, or bypass extension methods and use a static class directly - these won't pollute the type metadata in IntelliSense.
In extension methods, "this" can be null (due to how they compile into static method calls) so be careful and don't assume that "this" is not null (from the calling side this looks like a successful method call on a null target).
These are optional and not exhaustive, but I find they usually fall under the banner of "good" advice. YMMV.
The 'this type name' syntax is used for extension methods.
For example if I wanted to add a UnCamelCase method to a string (so I could do "HelloWorld".UnCamelCase() to produce "Hello World` - I'd write this:
public static string UnCamelCase(this string text)
{
/*match any instances of a lower case character followed by an upper case
* one, and replace them with the same characters with a space between them*/
return Regex.Replace(text, "([a-z])([A-Z])", "$1 $2");
}
this string text means the specific instance of the string that you're working with, and text is the identifier for it.
The # syntax allows for variable names that are ordinarily reserved.

Assign a method with default values to Func<> without those parameters?

I would like to be able to do the following:
Func<int,bool> tryMethodFunc = TryMethod;
Where TryMethod has a signature like:
bool TryMethod(int value, int value2 = 0, double value3 = 100.0)
I'm not opposed to breaking the method up into a curried format but that would be more work if there is a way to do this without that.
Optional parameters is a language feature, the compiler is responsible for translating the calls to methods with optional parameters to full call with values.
Look at this simple piece of code below,
public void GeneralMethod()
{
TestMethod(6);
}
public bool TestMethod(int a, int b = 8)
{
return true;
}
When you disassemble these methods, you will see that the C# compiler actually replaced the call to TestMethod with one parameter to a call with both the parameters. The screen shot from ildasm proves that,
Now, Coming to current problem, the line of code in question is trying to bind a Func with a method that has optional parameters. If C# compiler have to handle this, it has to ensure that the Func some knows the default values. While this could have been achieved by compiler, it completely defeats the purpose of Func.
Purpose of Func is to provides a way to store anonymous methods in a generalized and simple way." reference
Another similar question in stackoverflow can be found here
#Chris Sinclair's solution works around this by creating an anonymous method that takes one parameter and calls the TryMethod from the body of this anonymous method.

How do I Moq a method that has an optional argument in its signature without explicitly specifying it or using an overload?

Given the following interface:
public interface IFoo
{
bool Foo(string a, bool b = false);
}
Attempting to mock it using Moq:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
gives the following error at compile time:
An expression tree may not contain a call or invocation that uses optional arguments
I've found the issue above raised as an enhancement in Moq's list of issues and it appears to be assigned to the 4.5 release (whenever that is).
My question is: what should I do given that the above is not going to be fixed anytime soon? Are my options only to either explicitly set the default value of the optional parameter every time I mock it (which kind of defeats the point of specifying one in the first place) or to create an overload without the bool (like what I would have done prior to C# 4)?
Or has anyone come across a more clever way to overcome this issue?
I believe your only choice right now is to explicitly include the bool parameter in the setup for Foo.
I don't think it defeats the purpose of specifying a default value. The default value is a convenience for calling code, but I think that you should be explicit in your tests. Say you could leave out specifying the bool parameter. What happens if, in future, someone changes the default value of b to true? This will lead to failing tests (and rightfully so), but they will be more difficult to fix because of the hidden assumption that b is false. Explicitly specifying the bool parameter has another benefit: it improves the readability of your tests. Someone going through them will quickly know that there's one Foo function that accepts two parameters. That's my 2 cents, at least :)
As for specifying it every time you mock it, don't duplicate code: create and/or initialise the mock in a function, so that you only have a single point of change. If you really want to, you can overcome Moq's apparent short-coming here by duplicating Foo's parameters into this initialisation function:
public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
if(!b)
{
fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
}
else
{
...
}
}
Using Moq version 4.10.1 I have been able to do the following
With Interface:
public interface IFoo
{
bool Foo(string a, bool b = false);
}
And Mock
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>(), It.IsAny<bool>())).Returns(false);
Resolves a call to Foo with the first parameter okay
Just encountered this issue today, Moq doesn't support this use case.
So, seems that overriding the method would be sufficient for this case.
public interface IFoo
{
bool Foo(string a);
bool Foo(string a, bool b);
}
Now both methods are available and this example would work:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
In my case, my problem was that I forgot to include an It.IsAny<string>() call for one of my optional parameters. Once I had an It.Is... call for all of my parameters (including the optional ones) it compiled just fine.
Let's say your method is defined in your interface like below
Task<IDataResult<StripeSubModel>> CancelSub(List<string> list, bool? revert = false);
You can define your mock service like below
mockService.Setup(s => s.CancelSub(It.IsAny<List<string>>(), It.IsAny<bool>()))

Categories