泛型类型和继承混淆

本文关键字:继承 泛型类型 | 更新日期: 2023-09-27 18:21:46

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

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");

但我无法在添加注释"错误行"的行中抛出异常

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

泛型类型和继承混淆

如果像这样将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#中被称为逆方差和协方差。

网上还有很多其他材料。我建议你读一下。

有一件事我没有读过,我知道如何记住区别——这很容易。如果您的所有方法都返回T,那么您可以添加out(想想一个集合和返回集合中的项——它们从集合的中出来)。如果你的所有方法都接受T,那么你就可以添加in(同样,集合-你可以添加东西,它们会进入集合中的)。但是,如果您有同时执行这两种操作的方法,则不能将任一关键字添加到泛型类型参数中。同样,一旦你选择了一个关键词并对其进行编码或发布它,你就很糟糕;你总是可以稍后添加它,但一旦你选择了一个,你就会被它卡住。