简体   繁体   中英

defining a delegate that can return a type with a generic parameter

I have the following classes

public class MyClass
{
    public MyClass(){}
}

public class MyClass<T> : MyClass
{
    public MyClass(){}
}

I would like to define a delegate that can return Task<MyClass<T>> or Task<MyClass> .

I declared it as follows.

public delegate Task<T> MyFunc<out T>() where T : MyClass;

but I get an error

Invalid variance: The type parameter 'T' must be invariantly valid on 'MyFunc<T>.Invoke()'. 'T' is covariant.

If I don't use the out modifier and I use the delegate to return a MyClass<T> object like follows

public Task<MyClass> ff(MyFunc<MyClass> f)
{
    return f();
}

public void aa()
{
    ff(() => Task<int>.Run(() => new MyClass<int>()));
}

I get a different error

error CS0029: Cannot implicitly convert type 'System.Threading.Tasks.Task<MyClass<int>>' to 'System.Threading.Tasks.Task<MyClass>'
error CS1662: Cannot convert lambda expression to delegate type 'MyFunc<MyClass>' because some of the return types in the block are not implicitly convertible to the delegate return type

Is there any way to achieve what I want?

You can have a signature of the delegate without the constraint and a returning value Task<int> of the function like this:

    public delegate Task<T> MyFunc<T>();

    public Task<int> ff(MyFunc<int> f)
    {
        return f.Invoke();
    }

    public void aa()
    {
        ff(() => Task<int>.Run(() => 5 ));
    }

or if you want to use the MyClass in the delegate signature you should have the code reflecting this:

    public delegate Task<T> MyFunc<T>() where T : MyClass;

    public Task<MyClass<int>> ff(MyFunc<MyClass<int>> f)
    {
        return f.Invoke();
    }

    public void aa()
    {
        ff(() => Task<MyClass<int>>.Run(() => new MyClass<int>()));
    }

Hope this help.

Maybe I am confused about what you actually want, but if you just want the ff method to return Task<MyClass> like you stated in your comment to Daniele, then I'm not sure why you wouldn't just write something like this:

class Program
{
    public delegate Task<T> MyFunc<T>();

    public Task<MyClass> ff(MyFunc<MyClass> f)
    {
        return f();
    }

    public void aa()
    {
        ff(() => Task.Run(() => new MyClass()));
    }

}



public class MyClass
{
    public MyClass() { }
}

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