简体   繁体   中英

Overload generic List's Add with extension method

I would like to overload a generic list's Add method so I can use collection initializations like:

var x = new List<Tuple<string>> { { "1", "2" }, { "1", "2" } };

(Where Tuple is a simple custom implementation of a binary tuple.) However, I created an extension method, put a using directive in the cs file, and still get the "No overload for method 'Add' takes 2 arguments"-error.
Is it not possible to do (with an extension method)?

Extension method code:

namespace ExtensionMethods {
    public static class Extensions{
        public static void Add<T>(this List<Tuple<T>> self, T value1, T value2) {
            self.Add(new Tuple<T> { value1, value2 });
        }
    }
}

It is not possible via extension methods. In order to make this syntax working you have to create your own collection class which will have void Add(T value1, T value2) signature.

PS: What you've done is not overload and there is no way to overload anything in existing class.

UPDATE: Looks like my first sentence should be: "It is not possible via extension methods in C# "

In C# 6.0[0] Microsoft allows the use of extensions methods in collection initializers. hurray :)

And since this isn't a .NET Framework or CLR change, but a compiler change, this feature can be used with .NET 4.0.

So the following is now valid C# code. (Tested in Visual Studio 2015 RC)

class Program
{
    static void Main(string[] args)
    {
        var x = new List<Tuple<string,string>> { { "1", "2" }, { "1", "2" } };
    }
}
public static class Extensions
{
    public static void Add<T1,T2>(this List<Tuple<T1,T2>> self, T1 value1, T2 value2)
    {
        self.Add(Tuple.Create( value1, value2 ));
    }
}

C# 6 Features [0]

You cannot implement constructors using extension methods.Extension method is nothing but a static method which takes in an instance of an object. Hence you need to have an instance first to be able to pass to it.

But you can just use AddRange() of the List to initialise your list.

Extension methods can't overload any method defined on their target type simply because they are not members of the target type. Extension methods do not ADD anything to their target types. They are just compiler magic that allow them to be called as if they were methods defined on their target type. In reality, they are defined in a separate static type, hence they can't overload any method on their target type.

Behind the scenes, the compiler replaces any calls to your extension method with a call to Extensions.

It looks like you are trying to make C# behave like Ruby and initialize an array of objects by passing a set of values, or at least imitate the behavior of dictionary initialization. Unfortunately you can't do that without actually overloading List<>.

Collection initialization is just another bit of compiler magic that tries to find an Add method with as many arguments as there are items in the argument list. If it were otherwise you could define a conversion operator to convert a list to your Tuple type.

Why don't you just use the built-in object initializers? You'll just have to write a bit more code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM