Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a method overload based on closed generic type?

Tags:

c#

generics

Suppose I have three methods:

void Foo(MemoryStream v) {Console.WriteLine ("MemoryStream");}
void Foo(Stream v)       {Console.WriteLine ("Stream");}
void Foo(object v)       {Console.WriteLine ("object");}

I call method Foo passing first parameter of open generic type:

void Bar<T>()
{
    Foo(default(T)); //just to show the scenario
    //default(T) or new T() doesn't make a difference, null is irrelevant here
}

I want to call MemoryStream overload, so I close generic type of method Bar with MemoryStream:

Bar<MemoryStream>();

but the object overload is called. If I add generic constraint to Foo signature where T : Stream, then the Stream version is called.

Is there a way to dispatch method call to MemoryStream overload, based on open generic type T?

I don't want to use Delegate.CreateDelegate or other Reflection APIs. Just in the means of C# language. I'm probably missing something within the language itself.

Tried this scenario with value types as closed generic type and using static methods.

like image 931
Ilya Ivanov Avatar asked Oct 21 '13 10:10

Ilya Ivanov


People also ask

How can generic method be overloaded?

A generic method can also be overloaded by nongeneric methods. When the compiler encounters a method call, it searches for the method declaration that best matches the method name and the argument types specified in the call—an error occurs if two or more overloaded methods both could be considered best ...

Can we overload a generic method in C#?

Answer: Yes, we can overload a generic methods in C# as we overload a normal method in a class. Q- If we overload generic method in C# with specific data type which one would get called? Answer: Function with specific data type i.e int will be called.

What are generic constraints in c#?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.


1 Answers

What you describe is called "template specialization" and doesn't work in C#. It is available in C++ but still hasn't made its way to C#.

This has already been answered in "C# generic interface specialization". The short version is that you can't do it. You can work around it forcing runtime resolution but in this case using generics makes no sense. Generics should be used to use the same code on different types.

Perhaps there is another way of doing what you really want. I've run in similar situations when implementing the Strategy or Template Method patterns, where I want most of the code to work in the general case but modify some specific steps.

In such cases it's better to inject the custom steps to your class as interfaces, or even Func<> objects that specialize the behavior, when you actually create the "Template Method".

Of course, there are a lot of other ways to do this, some of which work better than others for specific problems

like image 98
Panagiotis Kanavos Avatar answered Sep 20 '22 04:09

Panagiotis Kanavos