How to distinguish between T and IList <T>

I have two methods:

public static int Insert<T>(this System.Data.IDbConnection connection, T param)
public static int Insert<T>(this System.Data.IDbConnection connection, IList<T> param)

When I try something like this:

connection.Insert(new List<Foo>());

the wrong method is called (first method).

How can I make it work?

+4
source share
4 answers

If there are general overloads that can be implicitly named the same, you should use an explicit call.

This code will cause a second overload.

connection.Insert<Foo>(new List<Foo>());
+5
source

This prototype:

public static int Insert<T>(this System.Data.IDbConnection connection, T param)

... will accept almost everything as param, because it has type restrictions on it. He will accept Foo, a IList<Foo>, a List<Foo>and all not Foo. Thus, it overrides the second prototype, a problem known as convergence.

, . , , :

public static int Insert<T>(this IDbConnection connection, T param) where T: Foo

, T Foo Foo. List<>, IList<> Foo, .

+2

,

connection.Insert<Foo>(new List<Foo>());

, .

connection.Insert((IList<Foo>)new List<Foo>());
+1

:

  • , .

    connection.Insert<Foo>(new List<Foo>());

    IList<T>:

    connection.Insert((IList<Foo>)new List<Foo>());

  • , , - - IList, :

    public static int Insert<T>(this IDbConnection connection, List<T> param)
    {
        return connection.Insert((IList<T>)param);
    }
    
  • - , , , - :

    public static int Insert<T>(this IDbConnection connection, T param)
    {
        if (typeof(T).GetInterfaces()
          .Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>)))
        {
            // method info retrieval should be written more carefully & cached in static var
            var method = MethodBase.GetCurrentMethod().DeclaringType.GetMethods()
              .Single(m => m.Name == "Insert" && m.GetParameters()
                .Select(p => p.ParameterType)
                .Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IList<>)));
            var generic = method.MakeGenericMethod(typeof(T).GenericTypeArguments[0]);
            return (int)generic.Invoke(null, new object[] { connection, param });
        }
    
        ...
    }
    
  • , - , .NET InsertRange - . , .

+1
source

Source: https://habr.com/ru/post/1674534/


All Articles