1

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

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。(我不想改变 bll declerations)。

4

1 回答 1

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和它的伙伴,在 C#in中称为逆变和协变。

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

我没有读过但我知道的一件事是如何记住差异——恕我直言,这很容易。如果您的所有方法都返回T,那么您可以添加out(想想一个集合并返回集合中的项目 - 它们来自集合)。如果您的所有方法都接受T,那么您可以添加in(再次,集合 - 您可以添加东西并将它们放入集合中)。但是,如果您有两种方法都可以,则不能将任一关键字添加到泛型类型参数。同样,一旦您选择了关键字和代码,或者发布了它,您就很糟糕;您以后可以随时添加它并且没问题,但是一旦您选择了一个,您就会坚持下去。

于 2014-09-14T21:29:35.863 回答