C#泛型类作为参数,T与泛型类的被调用方法相同
我想打电话:C#泛型类作为参数,T与泛型类的被调用方法相同,c#,generics,C#,Generics,我想打电话: Question<Entity> question = Question<Entity>.Create( Choice.Create(). AddFollowUpQuestion(Question.Create()). AddFollowUpQuestion(Question.Create()), Choice.Create() ); 问题= 问题,创建(
Question<Entity> question =
Question<Entity>.Create(
Choice.Create().
AddFollowUpQuestion(Question.Create()).
AddFollowUpQuestion(Question.Create()),
Choice.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()
);
问题=
问题,创建(
Choice.Create()。
AddFollowUpQuestion(Question.Create())。
AddFollowUpQuestion(Question.Create()),
Choice.Create()
);
我正在尝试清理一些代码,基本上只是添加语法糖,这样一些我必须做的定义更容易阅读
IntelisSense和编译器都知道,他们希望参数具有类型选择,因为它是泛型类的方法。但它仍然需要我为传递的参数键入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
{
}
公共类问题,其中T:实体
{
公共静态问题创建(参数选项[]选项)
{
返回新问题
{
选择=选择
};
}
私有选择[]选择{get;set;}
}
公共类选择,其中T:Entity
{
公共静态选择创建()
{
返回新选项();
}
公共选择添加后续问题(问题后续问题)
{
FollowUpQuestions.Add(followUpQuestion);
归还这个;
}
私有静态列表后续问题{get;set;}
}
公共抽象类实体
{
}
通常要做的事情是为factory方法创建非泛型类:
public static class Question {
public static Question<T> Create<T>(Choice<T> choice) {
return Question<T>.Create(choice);
}
}
...
Question<Entity> question = Question.Create(Choice<Entity>.Create());
公共静态类问题{
公共静态问题创建(选项){
返回问题。创建(选择);
}
}
...
Question=Question.Create(Choice.Create());
C#可以根据参数的类型推断出要调用的方法,但不能推断出要调用生成所需类型参数的方法的类的类型:“类型推断魔法”只有一种方式
本质上,您给编译器Choice.Create()
表达式及其结果被传递给期望Choice
的方法的事实,并要求它推断Choice
实际上是泛型类型(尽管系统中可能存在非泛型Choice
),它有一个Create()
方法,返回Choice
。虽然编译器可能做到这一点,但实现成本很高,而且可能是一个突破性的改变
但是,您可以创建一个通用的helper方法,为多个类提供相同的T
,如下所示:
static Question<T> MakeQuestion<T>() {
return Question<T>.Create(Choice<T>.Create());
}
现在您可以执行以下操作:
var qf = new QuestionFactory<Entity>();
var question = qf.CreateQuestion(
qf.CreateChoice().
AddFollowUpQuestion(qf.CreateQuestion()).
AddFollowUpQuestion(qf.CreateQuestion()),
qf.CreateChoice()
);
var qf=new QuestionFactory();
变量问题=qf.CreateQuestion(
qf.CreateChoice()。
AddFollowUpQuestion(qf.CreateQuestion())。
AddFollowUpQuestion(qf.CreateQuestion()),
qf.CreateChoice()
);
一种方法是将Question.Create()更改为不希望提供选项,而是创建选项本身。它使代码更简单,您可以实现您的目标
public class Question<T> where T : Entity
{
public static Question<T> Create()
{
return new Question<T>
{
Choice = Choice<T>.Create()
};
}
private Choice<T> Choice { get; set; }
}
public class Choice<T> where T : Entity
{
public static Choice<T> Create()
{
return new Choice<T>();
}
}
public abstract class Entity
{
}
公共类问题,其中T:实体
{
公共静态问题创建()
{
返回新问题
{
Choice=Choice.Create()
};
}
私有选择{get;set;}
}
公共类选择,其中T:Entity
{
公共静态选择创建()
{
返回新选项();
}
}
公共抽象类实体
{
}
根据上下文的不同,这可能是一个积极的变化,因为创建选项的责任转移到了问题上,换句话说,您将Question.Create()的调用方从创建选项的麻烦中抽象出来
另一方面,它增加了问题和选择的耦合。
首选哪一个取决于体系结构的其余部分
当然,我认为T在选择中确实是必要的。我明白这个想法,但恐怕在这种情况下它行不通。我在开篇文章中举了一个更复杂的例子,更清楚地表明我正在建立一种流畅的方式来添加选择,其中包含后续问题,而这些问题反过来又可以有选择……dasblinkenlight的答案有什么问题吗?太快了,伙计,这是周末;)我刚刚在评论中回复了他的回答。谢谢你解释为什么它不起作用。因为我正在尝试建立一种方法来流利地创建带有问题选择的问题。。。(我更新了开篇文章中的代码示例来说明这一点)我认为这不适合助手。恐怕我会把你的答复记为答案。让我考虑一下;)虽然不像我希望的那样令人满意,但你的解释似乎是正确的,你建议使用一家工厂确实可以为我解决这个问题。谢谢谢谢,但情况正好相反。理想情况下,我只会在最外层的问题上声明T的类型,并让c#magic告诉下面的所有方法。
var qf = new QuestionFactory<Entity>();
var question = qf.CreateQuestion(
qf.CreateChoice().
AddFollowUpQuestion(qf.CreateQuestion()).
AddFollowUpQuestion(qf.CreateQuestion()),
qf.CreateChoice()
);
public class Question<T> where T : Entity
{
public static Question<T> Create()
{
return new Question<T>
{
Choice = Choice<T>.Create()
};
}
private Choice<T> Choice { get; set; }
}
public class Choice<T> where T : Entity
{
public static Choice<T> Create()
{
return new Choice<T>();
}
}
public abstract class Entity
{
}