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.
Related
Why I cant overload Method with dynamic and object Parameters.
void Method(dynamic arg) // Member with same signature is already declared
{
Console.WriteLine("Dynamic");
}
void Method(object arg) // Member with same signature is already declared
{
Console.WriteLine("Not Dynamic");
}
But I can overload Method with dynamic and another type except object or dynamic it self.
void Method(dynamic arg)
{
Console.WriteLine("Dynamic");
}
void Method(string arg)
{
Console.WriteLine("Not Dynamic");
}
As you can see in the first example compiler can't discriminate two overloads.
I think the second example should not work too because string can be send to both overloads. However Compiler Prefers to call the overload with known type.
I've done some test to see how actually it works.
Method(""); // Prints: Not Dynamic
Method((dynamic)""); // Prints: Not Dynamic
Method(null); // Prints: Not Dynamic
Method(???); // Dynamic for any other type except string and null.
Consider first example works and compiler would decide like this:
Method(new object());// Prints: Not Dynamic
Method((object)5); // Prints: Not Dynamic
Method(???); // Prints: Dynamic for any other type except object and null.
So where is the confusion to the compiler? Why I cant have such overloads?
From the C# 5.0 specification, 4.7 The dynamic type:
The type dynamic has special meaning in C#. Its purpose is to allow dynamic binding, which is described in detail in §7.2.2.
dynamic is considered identical to object except in the following respects:
• Operations on expressions of type dynamic can be dynamically bound (§7.2.2).
• Type inference (§7.5.2) will prefer dynamic over object if both are candidates.
Because of this equivalence, the following holds:
• There is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
• Implicit and explicit conversions to and from object also apply to and from dynamic.
• Method signatures that are the same when replacing dynamic with object are considered the same signature
In fact, once your code is compiled, a method having dynamic as a parameter is effectively the same as if that same method were declared using object. It's simply that inside the method, the dynamic parameter can be used dynamically (i.e. with run-time binding).
Because of this, your first example pair of methods is essentially the same as if you'd declared both methods with the parameter type of object.
In your second example, just as you can have overloads where one has a parameter of object and the other a parameter of string, so too can you pair a method using dynamic with a method of the same name using string.
Per the overload resolution rules for C# (also in the specification), as long as the method parameter lists are different in ways that allow one method overload to be chosen as the "best" overload, no compile-time error will occur. In your specific example, passing anything other than a string to the method automatically excludes the method with string as a parameter. In the case where you do pass string, the overload resolution rules select the string overload as the "best" overload, so no compile error occurs.
public static class Utility {
public static void ShadowDeserializeFile<T, S>(this T target, FileInfo file)
where T : ShadowDeserializable<S> {
S shadow = SomeHelpingMethod(file);
target.ShadowDeserialize(shadow);
}
}
public interface ShadowDeserializable<S> {
void ShadowDeserialize(S shadow);
}
With above code I expect I can call it like:
var something = new SomeType(); //SomeType implements ShadowDeserializable<ShadowType>
something.ShadowDeserializeFile<ShadowType>(aFileInfoObj);
However Visual Studio issues error saying that using the generic method requires 2 type arguments. Only when calling as below it compiles:
something.ShadowDeserializeFile<SomeType,ShadowType>(aFileInfoObj);
I tried switching the order of type parameters in the method declaration, no difference.
How should I modify the declaration so that it could be called concisely as I expected?
Or is my expectation simply wrong as the extension type argument simply can't be omitted in this case?
There is no way to infer type of one parameter and specify another explicitly.You need to specify both types.Another option is to add a parameter of type S and then compiler will infer the second parameter's type for you based on what you pass to the method.Then you can call it without specifying any type. But if you don't need such parameter, specifying two types is the only option.
If specifying one parameter where two type is expected would be possible, it would cause ambiguity.Imagine what would happen if you have another method with the same name that has one generic argument.
I have worked on Java and new to .Net technology
Is it possible to declare a function in C# which accepts variable input parameters
Is there any C# syntax similar to the following Java syntax?
void f1(String... a)
Yes, C# has an equivalent of varargs parameters. They're called parameter arrays, and introduced with the params modifier:
public void Foo(int x, params string[] values)
Then call it with:
Foo(10, "hello", "there");
Just as with Java, it's only the last parameter which can vary like this. Note that (as with Java) a parameter of params object[] objects can easily cause confusion, as you need to remember whether a single argument of type object[] is meant to be wrapped again or not. Likewise for any nullable type, you need to remember whether a single argument of null will be treated as an array reference or a single array element. (I think the compiler only creates the array if it has to, but I tend to write code which avoids me having to remember that.)
Have a look at params (C# Reference)
The params keyword lets you specify a method parameter that takes a
variable number of arguments.
You can send a comma-separated list of arguments of the type specified
in the parameter declaration, or an array of arguments of the
specified type. You also can send no arguments.
No additional parameters are permitted after the params keyword in a
method declaration, and only one params keyword is permitted in a
method declaration.
As shown in the example the method is declared as
public static void UseParams(params int[] list)
{
for (int i = 0; i < list.Length; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine();
}
and used as
UseParams(1, 2, 3, 4);
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)
What is the Method Signature in the following
int DoSomething(int a, int b);
Return type is a part of signature or not???
Return type is not part of the method signature in C#. Only the method name and its parameters types (but not the parameter names) are part of the signature. You cannot, for example, have these two methods:
int DoSomething(int a, int b);
string DoSomething(int a, int b);
To be clear: Methods cannot be overloaded based on their return type. They must have a unique name, unique parameter types, or pass their arguments differently (e.g. using out or ref).
Edit: To answer your original question, the method signature for your method is:
DoSomething(int, int)
Note that this all applies to normal methods. If you're talking about delegates, then you should see keyboardP's answer. (Short version: return type IS part of the signature for a delegate).
Is the return type is a part of signature or not?
It depends on why you are asking the question. Why do you care?
There are two definitions of method signature. The C# language definition does not include the return type, and uses the signature of the method to determine whether two overloads are allowed. Two methods with the same signature are not allowed in a type. Since C# does not consider the return type to be a part of the signature, C# does not allow two methods that differ only in return type to be declared in the same type.
The CLR, however, does include the return type in the signature. The CLR allows for two methods to be in the same type that differ only in return type.
To be more specific: in C# the signature consists of the methods:
name
number of type parameters
number of formal parameters
type of each formal parameter
out/ref/value-ness of each formal parameter
with the following additional notes:
generic type parameter constraints are not part of the signature
return type is not part of the signature
type parameter and formal parameter names are not part of the signature
two methods may not differ only in out/ref
In the CLR the signature consists of:
name
number of type parameters
number of formal parameters
type of each formal parameter including modopts and modreqs
return type including modopts and modreqs
ref/value-ness of each formal parameter
Note that the CLR does not distinguish between "ref int" and "out int" at all when considering signatures. Note that the CLR does distinguish between modopt/modreq types. (The way that the C# compiler deals with modopt/modreq types is too complex to summarize here.)
From MSDN:
A return type of a method is not part of the signature of the method
for the purposes of method overloading. However, it is part of the
signature of the method when determining the compatibility between a
delegate and the method that it points to.
To clarify, in your example the return type is not part of the signature. However, when you're matching the signature of a delegate, it is considered part of the signature. From MSDN:
Any method that matches the delegate's signature, which consists of
the return type and parameters, can be assigned to the delegate. This
makes is possible to programmatically change method calls, and also
plug new code into existing classes. As long as you know the
delegate's signature, you can assign your own delegated method.
So I believe it's based on context. Most of the time, and as shown in your code, the return type is not part of it. However, in the context of delegation, it is considered part of it.
From MSDN:
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
Edit: That is from old documentation. It seems the definition of 'signature' has changed since then. Now a method has two different signatures, one for the purpose of overloading and one for the purposes of determining delegate compatibility. See keyboardP's answer below for more details.
DoSomething(int a, int b);
is the method signature,
int is the return type.
take a look at this :Signatures and overloading
The signature does not contain the return type. Neither the parameter names. In your case it would be DoSomething(int, int)
In the case when method have generic arguments understanding of signature becomes more confusing.
Generic types declaring on class level are considered as normal types.
But generic types declaring on method level are considered as index in method's generic arguments.
For example these all methods have different signatures.
class MyClass<TValue>
{
public void F(TValue v) { } // generics: 0, arg: TValue
public void F<X>(TValue v) { } // generics: 1, arg: TValue
public void F<X, Y>(TValue v) { } // generics: 2, arg: TValue
public void F<X>(X v) { } // generics: 1, arg: 0
public void F<X, Y>(X v) { } // generics: 2, arg: 0
public void F<X, Y>(Y v) { } // generics: 2, arg: 1
}