开发者

Why can't I overload a method with the same parameters if I choose different generic restraints?

开发者 https://www.devze.com 2023-02-18 21:09 出处:网络
If I do this in c# 4.0 .NET private static void myMethod<T>(int obj) where T : IDictionary { } private static void myMethod<T>(int obj) where T : ICollection

If I do this in c# 4.0 .NET

    private static void myMethod<T>(int obj) where T : IDictionary
    {


    }

    private static void myMethod<T>(int obj) where T : ICollection
    {


    }

I get the following error.

Type 'ConsoleApplication1.Program' already defines a member called 'myMethod' with the same parameter types

I would like to know why? As far as I see, both these methods can be called without ambiguity?

If I wanted the first method, I'd do this

myMethod<IDictionary>(50)

and second method

myMethod<ICollection>(40)
开发者_如何转开发

What scenario am I missing? And is there a way to achieve a set of overloaded methods with the same parameters but a different type?


Overload resolution in C# doesn't take constraints into account at all.

From the C# specification:

7.5.3 Overload resolution

Overload resolution is a binding-time mechanism for selecting the best function member to invoke given an argument list and a set of candidate function members.

The blog link by @Anthony Pegram is a much better read on the topic: Constraints are not part of the signature


Overloads are only based on function parameters. Return types and template parameters (more specifically: constraints) do not work for overloading a function. I can't tell you why this is (since I didn't write the language, and don't pretend to understand all their concerns). I can only tell you what the compiler will allow.

One reason that you might want to overload on constraints might be to try to accomplish the equivalent of C++ template specialization. Unfortunately, C# doesn't support this. .Net generics and C++ templates are extremely different beasts.

Regarding your specific example; there are two ways to solve this. Both require you to think about your problem differently.

The real problem is that the usage you are intending hurts your design. Overloading is really just syntactic sugar. Overloading helps people call your public interface. It doesn't actually help you internally. In fact, if the overloaded methods do significantly different things, it can make it much harder to reason about your code while you are debugging it, and when you have to come back and maintain it.

Since the code that calls these functions has to specify T, you aren't saving any maintenance costs by overloading the function. Instead, you could consider injecting the dependency (the collection) into these methods.

private static void myMethod(int obj, IDictionary dictionary)
{
    // do something with the dictionary here, setting private members while you do it
}

private static void myMethod(int obj, ICollection collection)
{
    // do something with the collection here, setting private members while you do it
}

If this solution would require you to duplicate your new Dictionary or new List calls too often, or if you want the method to control when the instance gets created, you can simply give up overloading.

private static void myMethodWithDictionary<T>(int obj) where T : IDictionary, new()
{
    // Create your new dictionary here, populate it, and set internal members
}

private static void myMethodWithCollection<T>(int obj) where T : ICollection, new()
{
    // Create your new collection here, populate it, and set internal members
}


What happens if you have a class such that public class Whatever : IDictionary, ICollection? The compiler wouldn't know which overload to use.

0

精彩评论

暂无评论...
验证码 换一张
取 消