C# 泛型类作为参数,T 与泛型类的调用方法相同

标签 c# generics

我想打电话:

Question<Entity> question = 
    Question<Entity>.Create(
        Choice.Create().
            AddFollowUpQuestion(Question.Create()).
            AddFollowUpQuestion(Question.Create()), 
        Choice.Create()
    );

但 C# 允许我做的最好的事情是:

Question<Entity> question = 
    Question<Entity>.Create(
        Choice<Entity>.Create().
            AddFollowUpQuestion(Question<Entity>.Create()).
            AddFollowUpQuestion(Question<Entity>.Create()), 
        Choice<Entity>.Create()
    );

我正在尝试清理一些代码,基本上只是添加语法糖,这样我必须做很多的一些定义更容易阅读。

intelisense 和编译器都知道他们期望参数是 Choice 类型,因为它是泛型类的一个方法。但它仍然需要我为传递的参数键入 T 的类型。

更抽象一点:我正在尝试创建一个顶级泛型类,其中所有也是泛型类型的属性都将对 T 使用相同的类型。

谁能帮我解决这个难题?或者至少解释一下为什么我必须一遍又一遍地输入相同的类型?

简化的类定义:

public class Question<T> where T : Entity
{
    public static Question<T> Create(params Choice<T>[] choices)
    {
        return new Question<T>
        {
            Choices = choices
        };
    }

    private Choice<T>[] Choices { get; set; }
}

public class Choice<T> where T : Entity
{
    public static Choice<T> Create()
    {
        return new Choice<T>();
    }

    public Choice<T> AddFollowUpQuestion(Question<T> followUpQuestion)
    {
        FollowUpQuestions.Add(followUpQuestion);

        return this;
    }

    private static List<Question<T>> FollowUpQuestions { get; set; }
}

public abstract class Entity
{

}

最佳答案

C# 可以根据参数的类型推断出您要调用的方法,但它无法推断出调用产生所需类型参数的方法的类的类型:“类型推断魔法” "只有一种方式。

本质上,您为编译器提供了 Choice.Create() 表达式以及它的结果被传递给期望 Choice<Entity> 的方法这一事实,并要求它推断 Choice 实际上是一个泛型类型(尽管事实上可能存在非泛型Choice 在系统中),它有一个返回 Create()Choice<T> 方法。尽管编译器可能会这样做,但实现起来会很昂贵,并且可能是一个重大变化。

但是,您可以制作一个通用的辅助方法,为多个类提供相同的 T,如下所示:

static Question<T> MakeQuestion<T>() {
    return Question<T>.Create(Choice<T>.Create());
}

现在你可以打电话了

Question<Entity> question = MakeQuestion<Entity>();

并且只传递一次类型参数。

编辑:就您编辑的更详细的示例而言,您应该能够通过引入在 Entity 上通用的工厂 来缩短 API,并允许您创建问题、跟进等。

class QuestionFactory<T> {
    public Question<T> CreateQuestion() {
        ...
    }
    public Choice<T> CreateChoice() {
        ...
    }
}

现在你可以这样做了:

var qf = new QuestionFactory<Entity>();
var question = qf.CreateQuestion(
    qf.CreateChoice().
        AddFollowUpQuestion(qf.CreateQuestion()).
        AddFollowUpQuestion(qf.CreateQuestion()), 
    qf.CreateChoice()
);

关于C# 泛型类作为参数,T 与泛型类的调用方法相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36100805/

相关文章:

java - 编译器如何推断 Java 泛型中的类型

c# - Azure blob 存储 - 获取 block 列表以错误的顺序返回未提交的 block

c# - 处理因变量的递归算法

c# - 拦截通过 DynamicProxy 返回通用 Task<> 的异步方法

swift - 具有关联类型和工厂模式的协议(protocol)?

Scala 协方差和下限类型说明

c# - HtmlAgilityPack SelectNodes,处理

c# - 尝试插入我的数据失败

c# - 临时存储文件

java - 通用数组类型转换