Why can't type arguments be deduced for generic types?

Default case

Suppose the following sample problem: I want to create a method that simply displays the number of elements in any collectionList<> .
I created the following static class with one method:

public static class MyClass
{
    public static void MyMethod<T>(T obj) where T : List<int> // sort of pointless, yes
    {
        Console.WriteLine(obj.Count);
    }
}    

Note that Tis a subclass List<int>. Now I can call:

List<int> li = new List<int>();
MyClass.MyMethod<List<int>>(li);

Now, the IDE tells me that "The specification of the type argument is redundant." It can infer a type from use:

List<int> li = new List<int>();
MyClass.MyMethod(li); // OK. li is List<int>, type argument is not required

General case

As far as you remember, I want to display the counter of List anyone . Something like this would be great:

public static void MyComplexMethod<T>(T obj) where T : List<any>
{
    Console.WriteLine(obj.Count);
}

However, this is not the correct syntax. I have to implement the following method:

public static void MyComplexMethod<T1, T2>(T1 obj) where T1 : List<T2>
{
    Console.WriteLine(obj.Count);
}

" ":

List<int> li = new List<int>();
MyClass.MyComplexMethod(li); // error
MyClass.MyComplexMethod<List<int>>(li); // error
MyClass.MyComplexMethod<List<int>, int>(li); // OK

MyClass.MyComplexMethod<List<double>, double>(new List<double>()); // OK
MyClass.MyComplexMethod<List<string>, string>(new List<string>()); // OK

// error. The type must be convertible in order to use...So, compiler knows it
MyClass.MyComplexMethod<List<string>, double>(new List<string>()); 

, , . List<int> - T1 List<int>, T2 - int, . ? (where T : List<any>)?

- , . , , WCF, :

public static void Call<TServiceProxy, TServiceContract>(Action<TServiceProxy> action)
    where TServiceProxy : ClientBase<TServiceContract>, new()
    where TServiceContract : class
{
    TServiceProxy serviceProxy = new TServiceProxy();
    try
    {
        action(serviceProxy);
        serviceProxy.Close();
    }
    catch (Exception ex)
    {
        serviceProxy.Abort();
        // Log(ex);
        throw;
    }
}

Service.Call<EchoServiceClient>(x => {
    int v = DateTime.Now.ToString();
    x.Echo(v);
}); // not working

Service.Call<EchoServiceClient, IEchoService>(x => {
    int v = DateTime.Now.ToString();
    x.Echo(v);
}); // not convenient, pointless. EchoServiceClient inherits from ClientBase<IEchoService>

where TServiceProxy : ClientBase<TServiceContract> serviceProxy.Abort(). , where TServiceProxy : ClientBase<any> , TServiceContract - where.

+4
1

, .

, ? action , . , . , a ClientBase<something> ? .

? . , ICommunicationObject, ClientBase<T>.

. :

  • .
  • , ICommunicationObject, / .

, :

public static void Call<T>(Action<T> action)
    where T: ICommunicationObject, new()
{
    T serviceProxy = new T();
    try
    {
        action(serviceProxy);
        serviceProxy.Close();
    }
    catch (Exception ex)
    {
        serviceProxy.Abort();
        throw;
    }
}

, , : , . , , , . , Foo<X>() Foo<X, Y>() - , , Foo<X>(), .

, , , , , inferring.

+2

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


All Articles