Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#泛型问题_C#_Generics - Fatal编程技术网

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:我试图实现前面问题的答案,但在这里被击中了。本想更新同一个问题,但我已将其标记为已回答。所以,我提出了另一个问题。不过,这个问题是关于前一个问题的实现部分。