I don't understand parameter declaration - c#

I got this assignment which to declare a method like this...
public List<Contact> GetLastContacts([int count = 20])
{
return this._entities.ContactsSet.ToList();
}
What I don't understand and can't find info about is [int count = 20] as parameter...
Anyone got an explanation on what they mean?
/Best regards!

int count = 20 in a parameter declares it as a default value for the parameter. It makes the parameter optional for callers (or rather look optional for callers).
So, in a method calling it you can do:
var contacts = GetLastContacts(); // Will compile to GetLastContacts(20)
Or, to use a value to override the default:
var contacts = GetLastContacts(35);
See Named and Optional arguments on MSDN.

public List<Contact> GetLastContacts(int count = 20) (no []) means the method has an int parameter called count, but that the parameter is optional, and if the caller leaves it out and just calls GetLastContacts() the default value for count is 20.
The square brackets are incorrect in C# code, but they can appear in documentation, tooltips etc. as an indication that the parameter is optional.

I guess this might be a combination of two ways to write "optional parameter". In C#, you can define a method with optional arguments if you specify a default argument value with "assignment" like
public List<Contact> GetLastContacts(int count = 20)
You can then either call
GetLastContacts(count)
to specify the count, or
GetLastContacts()
which uses the default value of 20.
The usage of [ ] in your code might be POSIX standardized way to write optional parameters, which has no reason to be there at all as it's not supported by C# language nor its documentation standards.

Related

Why can't an out parameter have a default value?

Currently when trying to do something in a method that takes an out parameter, I need to assign the value of the out parameter in the method body, e.g.
public static void TryDoSomething(int value, out bool itWorkerd)
{
itWorkerd = true;
if (someFavourableCondition)
{
// if I didn't assign itWorked variable before this point,
// I get an error: "Parameter itWorked must be assigned upon exit.
return;
}
// try to do thing
itWorkerd = // success of attempt to do thing
}
I'd like to be able to set a default value of the itWorked parameter so I don't have to arbitrarily set the value in the body of the method.
public static void TryDoSomething(int value, out bool itWorkerd = true)
{
if (someFavourableCondition)
{
// itWorked was already assigned with a default value
// so no compile errors.
return;
}
// try to do thing
itWorkerd = // success of attempt to do thing
}
Why is it not possible to assign a default value for an out parameter?
Default values are available for parameters passed by value. The parameter is still passed to the function but if the code omits the parameter, the compiler supplies the missing value.
Your proposed feature is quite different. Instead of the caller omitting to pass the value, you propose to allow the implementer of the function to omit setting the value. So, this is a quite different feature. Why was it not implemented? Here are some possible reasons:
Nobody thought to implement this feature.
The designers considered the feature and rejected it as not useful enough to be worth the cost of implementing.
The designers considered the feature and rejected it as being confusing because it uses similar syntax to default value parameters, but has a quite different meaning.
I appreciate this isn't exactly answering the original question, but I'm unable to contribute to the comments. I had the same question myself so found myself here.
Since C#7 now allows out parameters to effectively be variable declarations in the calling scope, assigning a default value would be useful.
Consider the following simple method:
private void ResolveStatusName(string statusName, out string statusCode)
{
statusCode = "";
if (statusName != "Any")
{
statusCode = statusName.Length > 1
? statusName.Substring(0, 1)
: statusName;
}
}
It felt intuitive to modify it like so:
private void ResolveStatusName(string statusName, out string statusCode = "")
{
if (statusName != "Any")
{
statusCode = statusName.Length > 1
? statusName.Substring(0, 1)
: statusName;
}
}
The intention was to not only declare the statusCode value, but also define it's default value, but the compiler does not allow it.
Even if it allowed you to give a default value like that, it would still require you to assign value for the parameter for all returns. So your default value will be overridden.
Default parameter values are the default value for parameters passed in to the method. You have to specify a variable to pass for an out parameter so that you can get the returned value.
Your first example, in a way, has a default, set at the beginning of the method.
The out method parameter keyword on a method parameter causes a method to refer to the same variable that was passed into the method. Any changes made to the parameter in the method will be reflected in that variable when control passes back to the calling method.
Declaring an out method is useful when you want a method to return multiple values. A method that uses an out parameter can still return a value. A method can have more than one out parameter.
To use an out parameter, the argument must explicitly be passed to the method as an out argument. The value of an out argument will not be passed to the out parameter.
A variable passed as an out argument need not be initialized. However, the out parameter must be assigned a value before the method returns.
Compiler will not allow you to use out parameter as default parameter because it is violating its use case. if you don't pass it to function you cannot use its value at calling function.
if you could call below function like TryDoSomething(123) then there is no use of out parameter because you will not be able to use value of itWorked
public static void TryDoSomething(int value, out bool itWorkerd = true)
{
if (someFavourableCondition)
{
// itWorked was already assigned with a default value
// so no compile errors.
return;
}
// try to do thing
itWorkerd = // success of attempt to do thing
}
If you have two calls to a method that uses 'out' or 'ref', and you want to avoid to split the method up in two, if one of the calls is not using these parameters, an elegant solution to avoid the warning from the compiler that "the value is not being used" (or something similar), is to use something like this:
method("hi", out _);
A method parameter declared with 'out' cannot have its value assigned by the caller. So a default value cannot be assigned during the call, either.
Also, you must always initialize an 'out' parameter in the method's body before using the parameter or returning from the method. This would overwrite any default value.
This is the whole point with the 'out' modifier. If you want a different behavior, check out the 'ref' and 'in' modifiers.

Get best matching overload from set of overloads

Let's say I have a class as follows:
public class AcceptMethods
{
public int Accept(string s, int k = 1)
{
return 1;
}
public int Accept(object s)
{
return 2;
}
public int Accept(IEnumerable<object> s)
{
return 7;
}
public int Accept(IList<object> s)
{
return 4;
}
}
Now, if I try to consume this in code, I use something like this:
object[] list = new object[] { "a", new object[0], "c", "d" };
Assert.AreEqual(7, list.Select((a)=>((int)new AcceptMethods().Accept((dynamic)a))).Sum());
The reason that it's 7, is because overload resolution prefers [IList<object>] over [IEnumerable<object>] and [object], and because [string, int=default] has preference over [object].
In my scenario, I'd like to get the best matching overload using reflection. In other words: 'best' is defined as 'c# overload resolution'. E.g.:
int sum = 0;
foreach (var item in list)
{
var method = GetBestMatching(typeof(AcceptMethods).GetMethods(), item.GetType());
sum += (int)method.Invoke(myObject, new object[]{item});
}
Assert.AreEqual(7, sum);
While the scenario I sketch has only 1 parameter, the solution I seek can have multiple parameters.
Update 1:
Because I received a comment that this is too difficult for SO due to the difficulties of overload resolution implementation (which I am well aware of), I feel inclined to send an update. To give my argument some power, this was my first attempt, which uses the default .NET binder that handles the overload resolution:
private MethodBase GetBestMatching(IEnumerable<MethodInfo> methods, Type[] parameters)
{
return Type.DefaultBinder.SelectMethod(BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
methods.ToArray(), parameters, null);
}
This version already seems to do simple overload resolution correctly, but fails to work with optional parameters. Because .NET afaik works with type binding like I show here, I suppose that the solution could be implemented fairly easy.
This is a massive subject, requires quite a lot of work and certainly cannot be wrapped up in an SO answer in my opinion. I suggest you read through the C# spec and read the formal rules defining overload resolution (also, please pay attention to generic methods) and try to implement them up to the point that satisfies your needs.
Update
Optional (i.e. parameters with default values) are not a trivial case - and the Reflection binder makes no attempt at all to fill them in - that's because it's a compiler's job to identify the default values, pull them out and inject them into a call to such a method.
You need a multi-pass approach that's something like this (note - does NOT include generics):
Search manually for a method whose number of parameters and types of those parameters match exactly the number and types of arguments you've got. If you find a match - use it and bunk out.
Now identify the 'candidate list' of methods for your overload selection (generally that's by name - you might also exclude generics here - unless you're going to try and bind those too).
If none of those methods have optional parameters then you might be able to go ahead and use the default binder as per your question to find the match (if not, you need a argument/parameter-ranking algorithm based on the types - if so, skip to 5).
Re-running through the candidate list built in 3), pull out all the optional parameters and incorporate their default values into your own parameter lists (you might need to build a separate set of parameters for each method at this point, including those that you have been supplied, but also the defaults).
Run your ranking algorithm for these methods built in 3) and possibly 4) to identify the best match (you seem to have a good handle on this so I'm not going to go through it all here - it's not a simple algorithm and I frankly can't quote it all verbatim here either!).
Your ranking algorithm should produce a clear winning method - i.e. with a unique high score or similar. If you get a clear winner, then that's the one you bind. Otherwise you have an ambiguity and you have to bunk out.
You might be interested in my own SO at this point - Default parameters and reflection: if ParameterInfo.IsOptional then is DefaultValue always reliable? - which should help you with identifying methods that have parameters with defaults, and how to lift them out.
For other people that want to do runtime overload resolution, this is a fairly complete description on how to implement it.
Important side note is that the 'dynamic' trick doesn't work in all scenario's as well (specifically: generics); it seems that the compiler is more flexible than runtime behavior.
Also note that this is not a complete algorithm/implementation (or at least I think that it isn't), but works in most cases including nevertheless. I found this to work in all cases that I encountered so far, including difficult cases like array covariance.
The scoring algorithm works as follows:
If parameter type == source type: score = 0
If the parameter is a generic type argument that is valid (generic constraints): score = 1
If the source type is implicitly convertible to the parameter type: score = 2 (see: http://msdn.microsoft.com/en-us/library/y5b434w4.aspx for all rules)
If you need to fill in a default parameter: score = 3
Otherwise calculate the score for compatibility score as below
The compatibility score is the most strict conversion between a type type A and type B (including and covariance, contravariance). For example, string[] has 1 conversion to IList (using object[] and then IList) and 2 conversions to IEnumerable (1. by using object[] and then IEnumerable or 2. by IEnumerable). Therefore, IList is the more strict conversion and is therefore selected.
Counting the number of conversions is easy:
int cnt = CountCompatible(parameter.ParameterType, sourceType.GetInterfaces()) +
CountCompatible(parameter.ParameterType, sourceType.GetBaseTypes()) +
CountCompatible(parameter.ParameterType, new Type[] { sourceType });
[...]
private static int CountCompatible(Type dst, IEnumerable<Type> types)
{
int cnt = 0;
foreach (var t in types)
{
if (dst.IsAssignableFrom(t))
{
++cnt;
}
}
return cnt;
}
To make sure that a better score is selected when a more strict conversion is used, I calculate score as 'score = 5 - 1.0 / (cnt + 2);'. The +2 ensures that you never divide by 0 or 1, leading to a score between 4 and 5.
To do overload resolution, select the method with the minimum score for all arguments. Make sure you enter default method arguments properly when invoking (see the excellent link by Andras above) and make sure you fill in the generic arguments before you return the method. If you encounter a draw for the best method: the best resolution is to throw an exception.
In case you wonder, yes... it's quite a bit of work to get it all working correctly... I plan to make a working version available in my framework once that's done. (You'll see the moment my profile has a working website link :-) )

function overload

Can I have two same function name with same parameters but different meaning.
For example:
public void test(string name)
public void test(string age)
Thank you.
No, you can't. The signature is not different - it doesn't matter what the parameter names are.
Methods are declared in a class or struct by specifying the access level such as public or private, optional modifiers such as abstract or sealed, the return value, the name of the method, and any method parameters. These parts together are the signature of the method.
http://msdn.microsoft.com/en-us/library/ms173114.aspx
Like a few other answers have stated, consider the type of data you're taking in. Name is indeed a typical string, but does age have to be? If you allow it to be a - for example - int then you can overload your method as you wish.
No, you cannot overload on a return type or a parameter name. Unlike some other languages (most notably, Objective C1) parameter name is not part of the signature of your function.
The signature of a method consists of the name of the method and the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. The signature of a method specifically does not include the return type, nor does it include the params modifier that may be specified for the right-most parameter.
1 even there it's not exactly the parameter name that becomes part of the selector.
You can have static and non-static methods with the same name, but different parameters following the same rules as method overloading, they just can't have exactly the same signature.
No.
Signatures and Overloading
If you need a method with different meaning why won't you create a method with a different name? It would be confusing to use the same method name for different things on the same object.
You could mix together these methods using optional parameters and default values:
public void test(string name = null, string age = null)
{
if (name != null)
{
// Do something
}
else if (age != null)
{
// Do something else
}
}
And you could call this method like that:
test(name: "John");
test(age: "30");
Not very clean, but still useable.
No - the compiler throws an error because compiler use parameters to detemine which method to call, not the return type.
NO.
An OVERLOADED FUNCTION must have different SIGNATURE.
i.e.- arguments should be different, either in terms of number of arguments or order of different datatypes arguments.

C# : overloading constructors with optional parameters & named arguments?

This isn't a question on proper coding practice, I'm just working through the semantics.
lets say I have the following constructors...
public FooClass(string name = "theFoo")
{ fooName = name; }
public FooClass(string name, int num = 7, bool boo = true) : this(name)
{ fooNum = num; fooBool = boo; }
is it possible to use named arguments thusly...?
FooClass foo1 = new FooClass(num:1);
// where I'm only passing one named argument, relying on the optionals to take care of the rest
or call the constructor FooClass(string, int, bool) with no arguments? as in...
FooClass foo2 = new FooClass();
Use of named and optional arguments affects overload resolution in the following ways:
A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter.
If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. Omitted arguments for optional parameters are ignored.
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.
http://msdn.microsoft.com/en-us/library/dd264739.aspx
Optional parameters are defined at the end of the parameter list, after any required parameters. If the caller provides an argument for any one of a succession of optional parameters, it must provide arguments for all preceding optional parameters. Comma-separated gaps in the argument list are not supported.
Also,
A named argument can follow positional arguments, as shown here.
CalculateBMI(123, height: 64);
However, a positional argument cannot follow a named argument. The following statement causes a compiler error.
//CalculateBMI(weight: 123, 64);

C# method call with parameter name and colon

I've begun to notice at times when I'm making method calls in C# that the names of the parameters for the method I'm calling will show up in the intellisense list appended with a colon, and that I can then format the method call thusly:
MethodCall(parameter1:value1, parameter2:value2);
Is this a new language feature? It reminds me of the way you can call stored procedures in SQL and specify parameter names like so:
spDoSomeStuff #param1 = 1, #param2 = 'other param'
Is this a similar feature? If so, to what end? If not, what is it and what is it to be used for.
It's a new feature. See here: http://msdn.microsoft.com/en-us/library/dd264739.aspx
Named parameters are standard in ObjectiveC for instance. It takes some time to get used to them but they are a good thing. Only from looking you can tell what a parameter is meant for.
It is worth mentioning, unlike optional parameters, you can skip certain arguments and pass only the parameters you are interested in.
public void Example(int required, string StrVal = "default", int IntVal = 0)
{
// ...
}
public void Test()
{
// This gives compiler error
// Example(1, 10);
// This works
Example(1, IntVal:10);
}
Named parameters allow you explicitly set the value of arguments in a custom order independent of the signature. Method signatures are defined by the argument types, ie, Foo( int i, bool b ), which will only accept arguments of type int and bool in that order. Named arguments allow you to pass b first and i second.
Scott Gu has introduced this new feature in his blog:
Optional Parameters and Named Arguments in C# 4
It's the Named and Optional Parameters that came in with C# 4.

Categories