泛型类型和继承混淆

时间:2014-09-14 21:08:09

标签: c# inheritance generic-method

我有一个类层次结构,如下所示:

public class Country : MainObj
public class MainObj : BaseEntity

我有以下业务逻辑类:

public class CountryBLL<TEntity> : CountryDLL<TEntity>,IBaseBLL<TEntity> where TEntity : Country
public class MainObjBLL<TEntity> : MainObjDLL<TEntity>, IBaseBLL<TEntity> where TEntity : MainObj

现在我要实现的是一个函数,我决定为此我应该得到哪个类和bll我为函数的返回类型添加了IBaseBLL接口

我的功能如下:

    public static IBaseBLL<T> GetProperBllFromObjName<T>(string entityName)
    { 
        IBaseBLL<T> baseBLL = null;
        switch (entityName)
        { 
            case "Country":
                CountryBLL<Country> aa = new CountryBLL<Country>(); 
                baseBLL = (IBaseBLL<T>) aa; //error line
                break;
        }


        return baseBLL;
    }

当我这样调用函数时:

IBaseBLL<BaseEntity> mainBll = GetProperBllFromObjName("Country");

但我无法在我添加评论&#34;错误行&#34;

的情况下排除异常

所以在这种情况下该怎么做。我唯一想要的是编写一个函数来决定我应该使用哪个bll。 (我不想改变bll declerations)。

1 个答案:

答案 0 :(得分:1)

如果您将out添加到IBaseBLL<T>这样的定义:<out T>它可能会有效(无法查看其余代码以确保没有否则),除非你在IBaseBLL<T>上有T作为输入参数的方法 - 这肯定会破坏它(因为它甚至不会编译)。

以下情况有效,但如果您取出out关键字,您将获得例外情况:

namespace MyProgram
{
    public class BaseEntity {}    
    public class CountryDLL<TEntity> {}    
    public class MainObjDLL<TEntity> {}    
    public interface IBaseBLL<out TEntity> {}    
    public class MainObj: BaseEntity {}    
    public class Country : MainObj {}    
    public class CountryBLL<TEntity> : CountryDLL<TEntity>,IBaseBLL<TEntity> where TEntity : Country {}    
    public class MainObjBLL<TEntity> : MainObjDLL<TEntity>, IBaseBLL<TEntity> where TEntity : MainObj {}    

    class Program
    {    
        public static IBaseBLL<T> GetProperBllFromObjName<T>(string entityName)
        { 
            IBaseBLL<T> baseBLL = null;
            switch (entityName)
            { 
                case "Country":
                    CountryBLL<Country> aa = new CountryBLL<Country>(); 
                    baseBLL = (IBaseBLL<T>) aa; //error line
                    break;
            }

            return baseBLL;
        }

        static void Main()
        {
            IBaseBLL<Country> c = GetProperBllFromObjName<Country>("Country");
            IBaseBLL<BaseEntity> d = GetProperBllFromObjName<BaseEntity>("Country");
        }
    }
}

使用out及其合作伙伴in在C#中称为contravariance and covariance

网上有很多其他资料。我建议阅读它。

有一件事,我没有读过,我知道的是如何记住差异 - 这很容易。如果您的所有方法都返回T,那么您可以添加out(想想集合并返回集合中的项目 - 它们来自 out 集合)。如果您的所有方法都接受T,那么您可以添加in(再次,收集 - 您可以添加内容,然后在集合中)。但是,如果您有两种方法,则无法将任何关键字添加到泛型类型参数。一旦你选择一个关键字和代码反对它或释放它你就是吮吸;你可以随时添加它,并且没关系,但是一旦你选择了它,你就会坚持下去。