I am trying to create a generic method in C#, which will call different methods based on the argument datatype in its body and process their result afterwards. I am trying to achieve this by creating a generic wrapper method and then provide several overloads of the processing method - including a generic one that'll be used if no specific overload is available.
When I call the processing method directly, appropriate version is correctly selected. However when I call it from the wrapper method it always selects the generic one, even if there's a matching overload for the specific datatype I passed to it.
Is there any way to adjust the code to make it behave the way I need to? Or do I have to use a different approach.
I need the code to be compatible with Mono 2.6.
using System;
class Program
{
static void Func<T>(T val)
{
Console.WriteLine("Generic Func");
}
static void Func(int val)
{
Console.WriteLine("Int Func");
}
static void Func(string val)
{
Console.WriteLine("String Func");
}
static void FuncWrap<T>(T val)
{
Console.Write("Wrap: ");
Func(val);
}
static void Main(string[] args)
{
Func(2);
Func("Potato");
Func(2.0);
FuncWrap(2);
FuncWrap("Potato");
FuncWrap(2.0);
Console.Read();
}
}
Is there any way correct this behavior?
It's already the correct behaviour according to the C# language specification. The overload of Func called within FuncWrap is normally determined at compile time, so it can't pick a different Func overload based on the execution-time type.
One way of changing the behaviour, however, is to use dynamic typing:
static void FuncWrap<T>(T val)
{
Console.Write("Wrap: ");
dynamic x = val;
Func(x);
}
That will now perform overload resolution at execution time based on the actual type of the value of x. This incurs a performance cost, but should do what you want it to.
Alternatively, you could hard-code knowledge of the overloads:
static void FuncWrap<T>(T val)
{
Console.Write("Wrap: ");
if (typeof(T) == typeof(string))
{
Func((string)(object)val);
}
else if (typeof(T) == typeof(int))
{
Func((int)(object)val);
}
else
{
Func(val);
}
}
That's clearly pretty horrible though.
Related
Why is the generic method called when both overloads would match?
public static void method1(object obj)
{
Console.WriteLine("Object");
}
public static void method1<T>(T t)
{
Console.WriteLine("Type T");
}
public static void Main(String args[])
{
method1("xyz"); //Will print "Type T";
}
There should not be any conflicts here, right?
Overloads are resolved by choosing the most specific overload. In this case, method1<string>(string) is more specific than method1(object) so that is the overload chosen.
There are details in section 7.4.2 of the C# specification.
If you want to select a specific overload, you can do so by explicitly casting the parameters to the types that you want. The following will call the method1(object) overload instead of the generic one:
method1((object)"xyz");
There are cases where the compiler won't know which overload to select, for example:
void method2(string x, object y);
void method2(object x, string y);
method2("xyz", "abc");
In this case the compiler doesn't know which overload to pick, because neither overload is clearly better than the other (it doesn't know which string to implicitly downcast to object). So it will emit a compiler error.
C# will always choose the most specific method it can.
When compiling
method1("xyz");
it will look for all methods with the specified name and then attempt to match parameters. The compiler will choose the method that is the most specific, in this case it would prefer
method1(string s)
over
method1<T>(T t) with T = string
and lastly
method1(object o)
Please note #Erik's excellent answer for an example where the compiler fails to decide.
Because you are already passing in T as a parameter so you don't need to type out method1<string>("xyz");you can just go method1("xyz");, .Net already knows it's a string. If you had method1 then it would be a different story.
Also since method1(object obj) doesn't take in a string as parameter it will favor the generic function first where it can infer T. If you were to change method1(object obj) to method1(string obj) it would favor it first then the generic.
How method overloading works
To find the matching signature of a method for a call, the compiler search in the type hierarchy from bottom to top as well in virtual table:
First in the class hierarchy,
Then in the interface hierarchy.
Because classes prevail on interfaces.
Indeed, before being of type of an interface, an object is of type of a class first of all.
And non generic signatures prevail over generic as reality and facts prevail over abstraction, unless using the generic parameter allow a call on the more specialized type of instance.
Applying the theory to the question
This call:
method1("xyz");
Match perfectly with:
void method1<T>(T t) { }
Before matching with:
void method1(object obj)
Because string is a specialized object and it can be used as a generic parameter to be more acurate.
On the other side, if you write:
void method1(string obj) { }
void method1<T>(T t) { }
The first method is so called.
Case study
var instance = new List<string>();
MyMethod(instance);
MyMethod((IEnumerable<string>) instance);
MyMethod<string>(instance);
MyMethod((object)instance);
void MyMethod<T>(List<T> instance) { }
void MyMethod<T>(IEnumerable<T> list) { }
void MyMethod<T>(T instance) { }
void MyMethod(object instance) { }
The first call calls the first method because instance is type of List (type matching).
The second call calls the second method because of the side cast (implementation).
The third call calls the third method because of the generic parameter specified to act on (templating).
The fourth call calls the fourth method because of the down cast (polymorphism).
I'm trying to output a value based on its type. Currently I'm creating a bunch of if-statements based on the type of T. Is there any better solution that makes the code look more concise?
public static void Output<T>(T data)
{
string dataStr = data.ToString();
if (typeof (T) == typeof(double))
{
dataStr = String.Format("{0:N4}", data);
}
Console.WriteLine(dataStr):
}
The only alternative is to avoid generics and provide explicit method overloads based on type:
public static void Output(Double data) { Console.WriteLine( "{0:N4}", data ); }
public static void Output(String data) { Console.WriteLine( "{0}", data ); }
public static void Output(Int32 data) { Console.WriteLine( "{0:G}", data ); }
// ...and so on
Note a downside to this approach is that overload selection is done at compile-time, not runtime, so this would fail: Output( (Object)someInt32Value );
it's batter option is Overloading,
Polymorphism:
When a message can be processed in different ways is called polymorphism. Polymorphism means many forms.
Polymorphism is one of the fundamental concepts of OOP.
Polymorphism provides following features:
It allows you to invoke methods of derived class through base class reference during runtime.
It has the ability for classes to provide different implementations of methods that are called through the same name.
Polymorphism is of two types:
Compile time polymorphism/Overloading
Runtime polymorphism/Overriding
Compile Time Polymorphism
Compile time polymorphism is method and operators overloading. It is also called early binding.
In method overloading method performs the different task at the different input parameters.
Runtime Time Polymorphism
Runtime time polymorphism is done using inheritance and virtual functions. Method overriding is called runtime polymorphism. It is also called late binding.
When overriding a method, you change the behavior of the method for the derived class. Overloading a method simply involves having another method with the same prototype.
Caution: Don't confused method overloading with method overriding, they are different, unrelated concepts. But they sound similar.
Method overloading has nothing to do with inheritance or virtual methods.
1. More info click here,
2. More info click here
using System;
class Test
{
static void Foo(int x, int y)
{
Console.WriteLine("Foo(int x, int y)");
}
static void Foo(int x, double y)
{
Console.WriteLine("Foo(int x, double y)");
}
static void Foo(double x, int y)
{
Console.WriteLine("Foo(double x, int y)");
}
static void Main()
{
Foo(5, 10);
}
}
One alternative would be maintaining a dictionary that matches Types to format strings.
The code is a little silly with one item, but any additional Types that need handling would only require an extra line in the dictionary:
public static void Output<T>(T data)
{
var formats = new Dictionary<Type, string>
{
{typeof (Double), "{0:N4}"}
};
var format = formats.Where(x => x.Key == typeof(T))
.Select(x => x.Value).SingleOrDefault();
string dataStr = data.ToString();
if (format != null)
dataStr = String.Format(format, data);
Console.WriteLine(dataStr);
}
To give credit where it's due, a similar question with a similar response.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
A problem with generic method overloading
Here is a simple code:
static class Example
{
static int DoIt(object o) { return 0; }
class A { }
static int DoIt(A a) { return 1; }
static int CallDoIt<X>(X x) { return DoIt(x); }
static void Main()
{
var a = new A();
System.Console.WriteLine(DoIt(a)); // returns 1 (as desired)
System.Console.WriteLine(CallDoIt(a)); // returns 0
}
}
The result looks very strange: the function DoIt() called directly returns different value from the case when it is called from another function. Is it expected behaviour in C#? If yes, how to achieve the desired behaviour (preferably without reflection)?
This is the expected behaviour, the knowledge of what type X is does not extend into the CallDoIt function. The overload of DoIt called from CallDoIt is determined statically based on the type of the argument x. Since X can be anything, the best (and only) candidate is DoIt(object).
You can get around this behaviour by delaying the dispatch to DoIt until runtime using dynamic:
static int CallDoIt<X>(X x) { return DoIt((dynamic)x); }
The other alternative is to provide a more specific version of CallDoIt:
static int CallDoIt(A a) { return DoIt(a); }
Method call DoIt(x) inside method CallDoIt<X>(X x) must work for any X type, so C# compiler chose to use DoIt(object o) overload.
If you restrict X type to derive from type A like this:
static int CallDoIt<X>(X x) where X : A { return DoIt(x); }
Then C# compiler will know it can chose DoIt(A a) overload since X type will always derive from type A. This also answers your second question of how to achieve the desired behaviour.
Yes, that is the expected behaviour. A generic method is compiled once for all possible arguments. During that single compilation, DoIt(x) cannot be resolved to DoIt(A), so it is DoIt(object), and that is what it will always be.
You can dynamically check the object type, or better yet, have .NET Framework do so for you:
static int CallDoIt(object x) { return DoIt((dynamic)x); }
Note that there is no benefit here to making CallDoIt generic: it would do exactly the same as this version. That means that CallDoIt((object)a) calls DoIt(A), not DoIt(object).
Add another overload for CallDoIt:
static int CallDoIt(A x) { return DoIt(x); }
This will make things work.
The overload resolution occurs at compile time (if no dynamic resolution needed) and most specific type for X(type parameter) is object.
The decision of choose calling method will be resolved at compile time. The C# compiler does not know what is the type X and choosed the method with DoIt(object o).
I am working with a code that contains following overloaded method in generic class:
public class A<T>
{
public void Process(T item) { /*impl*/ }
public void Process(string item) { /*impl*/ }
}
When parametrizing the class for string do I lose the possibility to call the version with generic parameter?
var a = new A<string>();
a.Process(""); //Always calls the non-generic Process(string)
Specific types take precedence over generic types.
For example, this is what I tested with in LINQPad.
void Main()
{
new A<string>().Process("Hello");
}
public class A<T>
{
public void Process(T item) { Console.WriteLine("T"); }
public void Process(string item) { Console.WriteLine("string"); }
}
// Output: string
If you have a problem with hiding the generic method, then you need to rethink something. By overloading a generic method with specific types, you are effectively saying, "Use the generic overload if you need to, but if you can, use the specific version, because it should know what is best."
There is one way I just discovered, but it's a bit cross-eyed. Because generics and overloading get resolved in build time, you can define a generic method:
public static CallerClass
{
public static CallGenericOverload<T>(GenericClass<T> cls, T val)
{
return cls.ProblemOverload(val);
}
//We can also make an extension method.
//We don't have to of course, it's just more comfortable this way.
public static CallGenericOverloadExtension<T>(this GenericClass<T> cls, T val)
{
return cls.ProblemOverload(val);
}
}
public GenericClass<T>
{
public string ProblemOverload(T val)
{
return "ProblemOverload(T val)";
}
public string ProblemOverload(string val)
{
return "ProblemOverload(string val)";
}
}
Now, if we do the following:
var genClass = new GenericClass<string>();
Console.WriteLine(genClass.ProblemOverload("")); //output: ProblemOverload(string val)
Console.WriteLine(CallerClass.CallGenericOverload(genClass, "")); //output: ProblemOverload(T val)
Console.WriteLine(genClass.CallGenericOverloadExtension("")); //output: ProblemOverload(T val)
You can use a similar trick if you define a generic class instead of a generic method. The important thing is that the parameter you transfer to ProblemOverload needs to be of type T rather than type string in the invocation. After all, the method CallGenericOverload knows it's getting a T at build time, so it's going to bind to the overload that accepts the parameter. It doesn't matter that it's actually going to get a string at runtime.
Yes. This is documented in the C# spec, section 7.5.3, overload resolution.
From 7.5.3.6:
"While signatures as declared must be unique, it is possible that substitution of type arguments results in identical signatures. In
such cases, the tie-breaking rules of overload resolution above will
pick the most specific member."
The example given in there states that in the case below, overload resolution for G<int>.F1 will pick non-generic
class G1<U>
{
int F1(U u);
int F1(int i);
}
The tie-breaking rule that applies here is outlined in 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.
Having done this before, I'm inclined to say "No," but there's always more knowledgable folks who would argue otherwise.
If memory serves, the runtime compiler chooses the most strongly typed overload to execute.
CLARIFICATION
My answer is badly worded, and I deserve the downvote.
The OP asked, "When parametrizing the class for string do I lose the possibility to call the version with generic parameter?" I wasn't answering that "No, you can't do that," but that "No, you don't lose the ability to call the version with the generic parameter."
I should have been more clear.
In C# it is possible to create higher order functions, ie. functions g taking functions as arguments. Say I want to create such a function which given a function f and returns another function extending its functionality. How do I define argument names for the returned enhanced method? The motivation being, that I'm working with higher order methods in general, some of which produce new methods.. and these can be difficult to use as there is no parameter names etc. attached to them.
An example illustrating how g and f respectively could be defined in C#:
I define a method Extend that can extens methods taking a T as argument and returning an S.
static class M
{
public static Func< T, S> Extend(Func< T, S> functionToWrap)
{
return (someT) =>
{
...
var result = functionToWrap(someT);
...
return result;
};
}
}
We can then extend a method on our class without changing the method.
class Calc2
{
public Func< int, int> Calc;
public Calc2()
{
Calc = M.Extend< int, int>(CalcPriv);
}
private int CalcPriv(int positiveNumber)
{
if(positiveNumber < 0) throw new Exception(...);
Console.WriteLine("calc " + i);
return i++;
}
}
Alas, the argument name positiveNumber is no longer available, since the only available information is Func<int, int> Calc. That is when I use the extended method by typing new Calc2().Calc(-1) I get no help from the IDE that in fact my argument is wrong.
It would be nice if we could define a delegate and cast it to this, however, this is not possible.
Any suggestions?
If you only want a fixed delegate type with named parameters then you can just define your own delegate type:
Func is just defined like this:
public delegate TResult Func<in T, out TResult>(T arg)
So you can define your own delegate type with the parametername you want.
But in your example you want to preserve the delegate type passed in, so this doesn't work here. In theory you could define your function like this:
public static T Extend(T functionToWrap)
{
}
Unfortunately there are no good generic constraints which restrict the input type to a delegate with the right signature(Or even just delegates at all). But without these constraints the implementation would become so ugly, and you'd lose so much static type safety that IMO it's not worth it.
One workaround is using:
new MyFunc(Extend(f))
where MyFunc defines the parameternames you want.
Or you could do the following:
public static T ConvertDelegate<T>(Delegate d)
{
if (!(typeof(T).IsSubclassOf(typeof(Delegate))))
throw new ArgumentException("T is no Delegate");
if (d == null)
throw new ArgumentNullException();
MulticastDelegate md = d as MulticastDelegate;
Delegate[] invList = null;
int invCount = 1;
if (md != null)
invList = md.GetInvocationList();
if (invList != null)
invCount = invList.Length;
if (invCount == 1)
{
return (T)(object)Delegate.CreateDelegate(typeof(T), d.Target, d.Method);
}
else
{
for (int i = 0; i < invList.Length; i++)
{
invList[i] = (Delegate)(object)ConvertDelegate<T>(invList[i]);
}
return (T)(object)MulticastDelegate.Combine(invList);
}
}
public static TDelegate Extend<TDelegate,TArg,TResult>(Func<TArg,TResult> functionToWrap)
where TDelegate:class
{
Func<TArg,TResult> wrappedFunc= DoTheWrapping(functionToWrap);
return ConvertDelegate<TDelegate>(wrappedFunc);
}
BTW the ConvertDelegate function can be used to get Co/Contravariance on Delegates even prior to .net 4.
It is possible to cast to a delegate with named parameters, by dynamically binding a newly constructed delegate to the underlying Func delegate method:
public delegate double CalcFunc(double value);
static class M
{
public static Func<T, S> Extend<T,S>(Func<T, S> functionToWrap)
{
return (someT) => functionToWrap(someT);
}
}
class Program
{
private static double Calc(double input)
{
return 2*input;
}
[STAThread]
static void Main()
{
Func<double, double> extended = M.Extend<double, double>(Calc);
CalcFunc casted = (CalcFunc)Delegate.CreateDelegate(typeof(CalcFunc), extended.Target, extended.Method);
Console.WriteLine(casted(2) + " == 4");
Console.WriteLine("I didn't crash!");
Console.ReadKey();
}
}
One word of warning: this will not do any compile-time checking of the cast. If the signatures don't match exactly, you'll get a bind failure at runtime (excepting special support for contravariance in .NET 4).
That's the beauty of anonymous delegates; they're anonymous. A Func is a delegate to a method that takes an int and returns an int. What the function actually does, and therefore the names of the parameters, is irrelevant.
The only way this would work is if Calc were of a named delegate type, defined with a signature identical to CalcPriv. It would all still work as written, including the anonymous extension, but you'd have a named parameter for Calc.
Another way to impart the information would be to xml-doc Calc with a ///<summary></summary> tag describing the parameter Calc was designed to take.
Lastly, you could derive from Func<T,TResult> to create a TakesPositiveInteger<T,TResult> class. This is going a little far, but if you wanna talk about self-documenting code...