试图利用通用参数的组合

Sha*_*rky 13 .net c# generics

这令人困惑,因为我看似矛盾的错误.

我使用的是仿制药,限制TSomething,然后制约UAnOperation<Something>.

我预计一个对象AnOperation<Something>从现在开始被认为是类型U.但是,我收到了错误:

Cannot implicitly convert type 'ConsoleApp1.AnOperation<T>' to 'U'

那真是怪了.好吧,我试着明确地将它投射到U,然后我收到了这个错误:

Cannot convert type 'ConsoleApp1.AnOperation<T>' to 'U' 其中也说明了 Cast is redundant

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    class MyClass<T, U>
        where T : Something
        where U : AnOperation<Something>
    {
        public U GetAnOperationOfSomething()
        {
            AnOperation<T> anOperation = new AnOperation<T>();

            return anOperation; // Cannot implicitly convert type 'ConsoleApp1.AnOperation<T>' to 'U'

            // return (U)anOperation; // Cannot convert type 'ConsoleApp1.AnOperation<T>' to 'U' also Cast is redundant
        }
    }

    public class Something
    {
    }

    public class AnOperation<T>
        where T : Something
    {
    }

}
Run Code Online (Sandbox Code Playgroud)

这里发生了什么事?

编辑:我试图了解语言级别的问题,而不是寻找实际问题的解决方法.

Sef*_*efe 11

你的约束几乎让你正确,但并不完全.你定义

 where U : AnOperation<Something>
Run Code Online (Sandbox Code Playgroud)

但是你创造了

AnOperation<T> anOperation = new AnOperation<T>()
Run Code Online (Sandbox Code Playgroud)

那不是一回事.如果您将约束更改为...

 where U : AnOperation<T>
Run Code Online (Sandbox Code Playgroud)

...你会好起来的.

另一个问题是,虽然每一个U都是一个AnOperation<T>,但不是每个AnOperation<T>都是一个U.当你宣布......

public U GetAnOperationOfSomething()
Run Code Online (Sandbox Code Playgroud)

...你正在保证方法返回的是一个U.AnOperation<T>不能满足那种保证.

你是用类型转换来解决这个问题的U.这违反了泛型类的目的,因为每个U必须是AnOperation<T>或者您将获得运行时异常.这使得整个类型参数变得U不必要.你真正想做的是创造一个U.您可以使用new()约束:

class MyClass<T, U>
    where T : Something
    where U : AnOperation<T>, new()
{
    public U GetAnOperationOfSomething()
    {
        U anOperation = new U();
        //...
        return anOperation;
    }
}
Run Code Online (Sandbox Code Playgroud)

new()约束保证U将有一个公共的默认构造函数,它可以调用.


Evk*_*Evk 5

T在你的类中是继承自的任何类Something. U是继承自的任何类AnOperation<Something>.假设您有这样的子类:

public class ChildOperation<T> : AnOperation<T> {}
Run Code Online (Sandbox Code Playgroud)

现在你U可能是ChildOperation<Something>,并且你不能返回父类(AnOperation<T>)的实例作为子类的实例(U这是ChildOperation<Something>).它T确实可能出错ChildSomething,因为AnOperation<Something>无法隐式转换为AnOperation<ChildSomething>.长话短说 - AnOperation<T>确实不能总是转换为你的U类型,所以编译是正确的.