I have a class Executive with the following code for that class:
public class Executive
{
public Executive(int Id = 0)
{
// Constructor 1
this.BaseSalary = 3000;
Console.Write("DONE");
}
public Executive()
{
// Constructor 2
Console.Write("done");
}
}
And in main I do the following:
Executive exec = new Executive()
It always calls Constructor 2.
Why doesn't it call Constructor 1 (since Id has a default value)?
That's how determining best method to call is done. Optional parameters without specified values are removed from arguments list when overload resolution is performed:
7.5.3.2 Better function member
For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list. Parameter lists for each of the candidate function members are constructed in the following way:
• The expanded form is used if the function member was applicable only in the expanded form.
• Optional parameters with no corresponding arguments are removed from the parameter list
• The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list.
Also later in the same paragraph:
In case the parameter type sequences {P1, P2, …, PN} and {Q1, Q2, …, QN} are equivalent (i.e. each Pi has an identity conversion to the corresponding Qi), the following tie-breaking rules are applied, in order, to determine the better function member.
• If MP is a non-generic method and MQ is a generic method, then MP is better than MQ.
• Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ.
• Otherwise, if MP has more declared parameters than MQ, then MP is better than MQ. This can occur if both methods have params arrays and are applicable only in their expanded forms.
• Otherwise if all parameters of MP have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in MQ then MP is better than MQ.
Which means that if you have two methods that both have applicable parameters but one requires to use optional parameter value and the other one doesn't, the one without optional value is better.
As MarcinJuraszek points out, this is just how it's determined which constructor should be called. When you call the parameterless constructor, that one is determined to be the best fit.
A solution to your problem would be to just explicitly call one constructor from the other:
public class Executive
{
public Executive(int ID)
{
//constructor 1
this.BaseSalary = 3000;
Console.Write("DONE");
}
public Executive():this(0)
{
//constructor 2
Console.Write("done");
}
}
Related
An overloaded method sample, for named parameter call:
internal static dynamic TestMethod(int P1a, int P1b, params dynamic[] P1c)
{
//Sample Code
}
[Overload: P2] //illustration : Overload Specification
internal static dynamic TestMethod(int P2a, int P2b, params dynamic[] P2c)
{
//Sample Code
}
Having a new set of code organization, is to specify which overload to use
using named parameters would resolve the problem or declare the method for overload selection;
TestMethod(P2: 1, 1,2,3,4,5);
They two features are not compatible. You would have to construct the array yourself, rather than having the compiler do that for you (an array is always constructed either way).
How do we know they're not compatible? From Argument lists:
An argument with an argument_name is referred to as a named argument, whereas an argument without an argument_name is a positional argument. It is an error for a positional argument to appear after a named argument in an argument_list.
Note that last sentence - you cannot have positional arguments after a named argument.
Runtime evaluation of argument lists:
Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter array
...
When a function member with a parameter array is invoked in its expanded form, the invocation must specify zero or more positional arguments for the parameter array ...
(My emphasis)
That is, the params feature only works with positional arguments.
I tried the below code
class Sample
{
public void Display(int a, float b)
{
Console.WriteLine("value of a = " + a);
Console.WriteLine("value of b = " + b);
}
public void Display(float a, float b)
{
Console.WriteLine("value of a = " + a);
}
}
class Program
{
static void Main(string[] args)
{
Operation obj2 = new Operation();
obj2.Display(5, 5);
Console.ReadKey();
}
}
The output is
value of a = 5
value of b = 5
How does C# compiler know which function to call??
However if the method signatures were
public void Display(int a, float b)
public void Display(float a, int b)
I get a compile time error saying Call is ambiguous. How is it that the compiler is now unable to differentiate?
What you are asking is how method overload resolution works. According to the C# language specification, the rule to find the best method is:
Given an argument list A with a set of argument types {A1, A2, ...,
AN} and two applicable function members MP and MQ with parameter types
{P1, P2, ..., PN} and {Q1, Q2, ..., QN}, MP is defined to be a better
function member than MQ if
for each argument, the implicit conversion
from AX to PX is not worse than the implicit conversion from AX to QX,
and
for at least one argument, the conversion from AX to PX is better
than the conversion from AX to QX.
When performing this evaluation, if
MP or MQ is applicable in its expanded form, then PX or QX refers to a
parameter in the expanded form of the parameter list.
Update
The above explanation is from the VS. NET 2003 specification, and should be considered outdated. The C# speficiation for VS 2015 can be found in the installation folder of VS 2015, at C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC#\Specifications\1033
The specification for the "better function member" reads at follows:
7.5.3.2 Better function member
For the purposes of determining the better function member, a
stripped-down argument list A is constructed
containing just the argument expressions themselves in the order they
appear in the original argument list.
Parameter lists for each of the
candidate function members are constructed in the following way:
The expanded form is used if the function member was applicable only
in the expanded form.
Optional parameters with no corresponding
arguments are removed from the parameter list
The parameters are
reordered so that they occur at the same position as the corresponding
argument in the argument list.
Given an argument list A with a set of
argument expressions { E1, E2, ..., EN } and two applicable function
members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1,
Q2, ..., QN }, MP is defined to be a better function member than MQ if
for each argument, the implicit conversion from EX to QX is not
better than the implicit conversion from EX to PX, and
for at least
one argument, the conversion from EX to PX is better than the
conversion from EX to QX.
When performing this evaluation, if MP or MQ
is applicable in its expanded form, then PX or QX refers to a
parameter in the expanded form of the parameter list.
In case the
parameter type sequences {P1, P2, …, PN} and {Q1, Q2, …, QN} are
equivalent (i.e. each Pi has an identity conversion to the
corresponding Qi), the following tie-breaking rules are applied, in
order, to determine the better function member.
If MP is a
non-generic method and MQ is a generic method, then MP is better than
MQ.
Otherwise, if MP is applicable in its normal form and MQ has a
params array and is applicable only in its expanded form, then MP is
better than MQ.
Otherwise, if MP has more declared parameters than
MQ, then MP is better than MQ. This can occur if both methods have
params arrays and are applicable only in their expanded forms.
Otherwise if all parameters of MP have a corresponding argument
whereas default arguments need to be substituted for at least one
optional parameter in MQ then MP is better than MQ.
Otherwise, if
MP has more specific parameter types than MQ, then MP is better than
MQ. Let {R1, R2, …, RN} and {S1, S2, …, SN} represent the
uninstantiated and unexpanded parameter types of MP and MQ. MP’s
parameter types are more specific than MQ’s if, for each parameter, RX
is not less specific than SX, and, for at least one parameter, RX is
more specific than SX:
A type parameter is less specific than a
non-type parameter.
Recursively, a constructed type is more specific
than another constructed type (with the same number of type arguments)
if at least one type argument is more specific and no type argument is
less specific than the corresponding type argument in the other.
An
array type is more specific than another array type (with the same
number of dimensions) if the element type of the first is more
specific than the element type of the second.
Otherwise if one
member is a non-lifted operator and the other is a lifted operator,
the non-lifted one is better.
Otherwise, neither function member is
better.
Another good source is the explanation on C# in Depth by Jon Skeet.
I have two overloaded generic methods:
T Foo<T>(T t) { Console.WriteLine("T"); return t; }
T Foo<T>(int i) { Console.WriteLine("int"); return default(T); }
When I try to call Foo as follows on my computer:
Foo(5);
I get no compiler errors or warnings, and the first method with the generic argument is called (i.e. the output is T). Will this be the case in all C# incarnations and on all platforms? In that case, why?
On the other hand, if I explicitly specify the type in the generic call:
Foo<int>(5);
the second method with the int argument is called, i.e. the output is now int. Why?
I am using different argument names in my two method overloads, so the output from the following calls are as expected:
Foo<int>(t: 5); // output 'T'
Foo<int>(i: 5); // output 'int'
If I am calling the first method, I can even leave out the type specification:
Foo(t: 5); // output 'T'
But if I try to compile this:
Foo(i: 5);
I get an error The type arguments for method 'Foo(int)' cannot be inferred from the usage. Try specifying the type arguments explicitly. Why cannot the compiler deal with this call?
Note These tests have been performed with LinqPad on a Windows 8 x64 system (in case that is relevant to the results...)
Last question
Since you specified (by parameter name) that it should call the overload that takes an int parameter, the compiler has no idea what to pass for T.
First question
Because of this, Foo(5) only matches one overload (Foo<T>()).
Therefore, it must only call Foo<T>().
Second question
When you explicitly specify a type argument (<int>), both overloads are applicable.
In that case, Foo(int) is better, since its parameter is not of generic type.
As per the C# spec §7.5.3.2:
Otherwise, if MP has more specific parameter types than MQ, then MP is better than MQ. Let {R1, R2, …, RN} and {S1, S2, …, SN} represent the uninstantiated and unexpanded parameter types of MP and MQ. MP’s parameter types are more specific than MQ’s if, for each parameter, RX is not less specific than SX, and, for at least one parameter, RX is more specific than SX:
A type parameter is less specific than a non-type parameter.
(emphasis added)
public enum EnumTest
{
EnumEntry
}
public class TestClass
{
public string FunctionMember(string s, EnumTest t = EnumTest.EnumEntry)
{
return "Normal";
}
public string FunctionMember<T>(T t)
{
return "Generic";
}
}
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
Console.WriteLine(t.FunctionMember("a"));
}
}
This prints "Generic". Removing , EnumTest t = EnumTest.EnumEntry makes it print "Normal".
And yet the standard appears to be pretty clear, from 14.4.2.2 Better function member the first discriminator to be applied is:
If one of MP and MQ is non-generic, but the other is generic, then the non-generic is better.
Am I missing something or compiler bug?
You are missing something. And that is the following:
You call the method with one parameter. There is only one method that has one parameter, the generic one. So that's the one that's chosen.
Only if it didn't find a matching method it would look at other methods with optional parameters.
References:
C# 4.0 Specification, last paragraph in 21.4:
As a tie breaker rule, a function member for which all arguments where explicitly given is better than one for which default values were supplied in lieu of explicit arguments.
MSDN, heading "Overload resolution", last bullet point:
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.
The C# Language Specification, Chapter "7.5.3.2 Better function member":
Parameter lists for each of the candidate function members are constructed in the following way:
The expanded form is used if the function member was applicable only in the expanded form.
Optional parameters with no corresponding arguments are removed from the parameter list
It continues like this:
Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN } [...]
At this point the method with the optional parameter is already out of the game. N is 1, but that method has two parameters.
The docs say:
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.
In other words, the method without any optional arguments will be preferred.
With default values for method parameters the overload resolution got extended.
Conceptually the method overload resolution from pre v4 will be run. If that finds a match that match will be used. (Conceptually because this is not a description of how it works but how you can think of it)
In your case it finds exactly one match being your generic method
If it does not find a match it will look for methods that has a partial match and where the match can be completed with default values. In your case your none generice method would be found in this run however the resolution never comes this far due to already having found a match.
When removing the second paramter you end up in a situation where there's a generic and a non generic match. And the rule you qoute kicks in picking the non-generic.
All in all a good rule of thumb is that the most specific available method will be chosen.
A non-generic method that matches is more specific than a generic because the type can't vary.
A method with default parameters is less specific than one where the argument count matches the parameter count (the numbers are an exact match)
if two methods are available but one takes an argument of IFoo and the other takes a Foo (implemeting IFoo) then the latter will be chosen when passing a Foo object as argument because it's an exact match Ie. more specific
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generic methods and method overloading
Ok, I hit this one by accident... Giving this situation:
class Program {
static void Main( string[ ] args ) {
var obj = new gen<int>( );
Console.Write( obj[ 1 ] );
Console.ReadKey( );
}
}
class gen<T> {
public int this[ T i ] { get { return 2; } }
public int this[ int i ] { get { return 1; } }
}
It will always print 1. I would have expected for the compiler to complain, or the runtime to crash and burn and melt the CPU, but no, it is happy to print '1'
Of course I can make a choice to return either if I use any other type for the generic parameter. For giggles, I try using UInt as the generic type parmater, and I can differentiate between the calls, so the questions are:
Why C# does not freak out? Shouldn't Anders Hejlsberg feel a disturbance in the force?
How can I restrict a generic parameter from certain types? As in this T can be anything but ints (but long are OK)
I believe this is specified in section 7.5.3.2 of the C# 4 spec (Better Function Member).
Otherwise, if MP has more specific parameter types than MQ, then MP is better than MQ [...]
A type parameter is less specific than a nontype parameter
[...]
So here, the member with the T parameter is less specific than the member with the int parameter.
Try to design your way out of this one simply by not overloading like this. It's hard for indexers of course, but you could always provide methods instead (or possibly as well, as a fall-back).
EDIT: Note that if you have overloaded methods where both are type parameters, the compiler will complain:
public class Foo<T1, T2>
{
public void Bar(T1 t1) {}
public void Bar(T2 t2) {}
}
...
Foo<int, int> foo = new Foo<int, int>();
foo.Bar(10); // Error
Here neither method is more specific.
How can I restrict a generic parameter from certain types? As in this T can be anything but ints (but long are OK)
This is really an entirely separate question, but basically you can't. You can constrain type parameters in various ways, but not by explicitly including and excluding types. See the MSDN page on constraints for more information.
As Eric Lippert says:
The C# specification says that when you have a choice between calling ReallyDoIt(string) and ReallyDoIt(string) – that is,
when the choice is between two methods that have identical signatures,
but one gets that signature via generic substitution – then we pick
the “natural” signature over the “substituted” signature.
Also this process described in C# spec 7.5.3.2 (Better function member):
In case the parameter type sequences {P1, P2, …, PN} and {Q1, Q2, …, QN} are equivalent (i.e. each Pi has an identity conversion to the corresponding Qi), the following tie-breaking rules are applied, in order, to determine the better function member.
If MP is a non-generic method and MQ is a generic method, then MP is better than MQ (as John pointed, this is true when you have generic method, not generic type)
...
Otherwise, if MP has more specific parameter types than MQ, then MP is better than MQ. Let {R1, R2, …, RN} and {S1, S2, …, SN} represent the uninstantiated and unexpanded parameter types of MP and MQ. MP’s parameter types are more specific than MQ’s if, for each parameter, RX is not less specific than SX, and, for at least one parameter, RX is more specific than SX:
A type parameter is less specific than a non-type parameter (this is your case - thus methods are not generic, and inferred parameter type equals to non-generic parameter type)
The C# compiler always chooses the more-specific versus the more-generic method if the call could fit in both =). That's why it doesn't freak out, he just follows his rules.
C# compiler doesn't freak out because both method are valid, and both can be called.
Here's an example that return "2":
Gen<Form> gen = new Gen<Form>();
textBox1.Text = gen[this].ToString();
Where "this" is a form. Of course, using an index accessor as an object instead of a number... Well, whatever, it works.
But like everybody else said, the compiler will prefer the explicit over the implicit.