C#泛型问题
我有什么? 我有一个抽象类,C#泛型问题,c#,generics,C#,Generics,我有什么? 我有一个抽象类,QueryExecutor和派生类,SqlQueryExecutor,如下所示 abstract class QueryExecutor<T> { public abstract T Execute(); } class SqlQueryExecutor<T> : QueryExecutor<T> where T:ICollection { public override T Execute() {
QueryExecutor
和派生类,SqlQueryExecutor
,如下所示
abstract class QueryExecutor<T>
{
public abstract T Execute();
}
class SqlQueryExecutor<T> : QueryExecutor<T> where T:ICollection
{
public override T Execute()
{
Type type = typeof(T);
// Do common stuff
if (type == typeof(ProfileNodeCollection))
{
ProfileNodeCollection nodes = new ProfileNodeCollection();
// Logic to build nodes
return (T)nodes;
}
else
{
TreeNodeCollection nodes = new TreeNodeCollection();
Logic to build nodes
return (T)nodes;
}
}
}
抽象类查询执行器
{
公共摘要T Execute();
}
类SqlQueryExecutor:QueryExecutor,其中T:ICollection
{
公共重写T Execute()
{
类型=类型(T);
//做普通的事情
if(type==typeof(ProfileNodeCollection))
{
ProfileNodeCollection节点=新建ProfileNodeCollection();
//构建节点的逻辑
返回(T)节点;
}
其他的
{
TreeNodeCollection节点=新的TreeNodeCollection();
构建节点的逻辑
返回(T)节点;
}
}
}
我想做什么?
在Execute()
方法的实现中,我想构造适当的ICollection
对象并返回它
我面临什么问题?
在Execute()
方法中,行return(T)节点代码>显示以下编译时错误:
无法将类型“WebAppTest.ProfileNodeCollection”转换为“T”
你知道我该怎么解决这个问题吗
提前谢谢 好的,一种简单的修复方法是让编译器不太了解正在发生的事情,这样它就可以将其推迟到CLR:
return (T)(object)nodes;
您可以将其放在单个位置,并在赋值时使用隐式转换到对象
:
object ret;
// Do common stuff
if (type == typeof(ProfileNodeCollection))
{
ProfileNodeCollection nodes = new ProfileNodeCollection();
// Logic to build nodes
ret = nodes;
}
else
{
TreeNodeCollection nodes = new TreeNodeCollection();
Logic to build nodes
ret = nodes;
}
return (T)ret;
这不太令人愉快,但应该行得通。不过,为不同的集合类型创建单独的派生类可能会更好—可能会将公共代码放在抽象基类中。好的,解决这个问题的一个简单方法是让编译器不太了解正在发生的事情,这样它就可以将它推迟到CLR:
return (T)(object)nodes;
您可以将其放在单个位置,并在赋值时使用隐式转换到对象
:
object ret;
// Do common stuff
if (type == typeof(ProfileNodeCollection))
{
ProfileNodeCollection nodes = new ProfileNodeCollection();
// Logic to build nodes
ret = nodes;
}
else
{
TreeNodeCollection nodes = new TreeNodeCollection();
Logic to build nodes
ret = nodes;
}
return (T)ret;
这不太令人愉快,但应该行得通。不过,为不同的集合类型创建单独的派生类可能会更好——可能会将公共代码放在抽象基类中。我会选择在这里分离关注点。您甚至可以有一个QueryExecutor
工厂,根据集合的类型提供正确的QueryExecutor
class ProfileSqlQueryExecutor : QueryExecutor<ProfileNodeCollection>
{
public override ProfileNodeCollection Execute()
{
ProfileNodeCollection nodes = new ProfileNodeCollection();
// Logic to build nodes
return nodes;
}
}
class TreeSqlQueryExecutor : QueryExecutor<TreeNodeCollection>
{
public override TreeNodeCollection Execute()
{
TreeNodeCollection nodes = new TreeNodeCollection();
Logic to build nodes
return nodes;
}
}
class ProfileSqlQueryExecutor:QueryExecutor
{
公共重写配置文件NodeCollection执行()
{
ProfileNodeCollection节点=新建ProfileNodeCollection();
//构建节点的逻辑
返回节点;
}
}
类TreeSqlQueryExecutor:QueryExecutor
{
公共重写TreeNodeCollection执行()
{
TreeNodeCollection节点=新的TreeNodeCollection();
构建节点的逻辑
返回节点;
}
}
我会选择在这里分离关注点。您甚至可以有一个QueryExecutor
工厂,根据集合的类型提供正确的QueryExecutor
class ProfileSqlQueryExecutor : QueryExecutor<ProfileNodeCollection>
{
public override ProfileNodeCollection Execute()
{
ProfileNodeCollection nodes = new ProfileNodeCollection();
// Logic to build nodes
return nodes;
}
}
class TreeSqlQueryExecutor : QueryExecutor<TreeNodeCollection>
{
public override TreeNodeCollection Execute()
{
TreeNodeCollection nodes = new TreeNodeCollection();
Logic to build nodes
return nodes;
}
}
class ProfileSqlQueryExecutor:QueryExecutor
{
公共重写配置文件NodeCollection执行()
{
ProfileNodeCollection节点=新建ProfileNodeCollection();
//构建节点的逻辑
返回节点;
}
}
类TreeSqlQueryExecutor:QueryExecutor
{
公共重写TreeNodeCollection执行()
{
TreeNodeCollection节点=新的TreeNodeCollection();
构建节点的逻辑
返回节点;
}
}
一小时前您已经问过这个问题:设计问题-通用基类和不同的返回类型:我不知道为什么会出现这个问题,但这是对泛型的滥用,我无论如何都不想回答。。。泛型的全部要点是它们应该是泛型的,并且不应该包含不同具体类型的t
的特殊行为(有关更多详细信息,请参见Liskov替换原则)。如果你在做这类事情,最好将ProfileNodeCollectionQueryExecutor
和TreeNodeCollectionQueryExecutor
作为单独的类(即,如果你的情况需要多态性,那么就使用它)。@Mitch-Wheat:我试图实现前面问题的答案,但在这里被击中了。本想更新同一个问题,但我已将其标记为已回答。所以,我提出了另一个问题。不过,这个问题是关于前一个问题的实现部分。您一小时前已经问过这个问题:设计问题-通用基类和不同的返回类型:我不知道为什么会出现这个问题,但这是对泛型的滥用,我无论如何都不想回答。。。泛型的全部要点是它们应该是泛型的,并且不应该包含不同具体类型的t
的特殊行为(有关更多详细信息,请参见Liskov替换原则)。如果你在做这类事情,最好将ProfileNodeCollectionQueryExecutor
和TreeNodeCollectionQueryExecutor
作为单独的类(即,如果你的情况需要多态性,那么就使用它)。@Mitch-Wheat:我试图实现前面问题的答案,但在这里被击中了。本想更新同一个问题,但我已将其标记为已回答。所以,我提出了另一个问题。不过,这个问题是关于前一个问题的实现部分。