这里有另一个我想不到的简单问题。
我有两节课:
namespace Assets
{
public class BaseAsset
{
// Code here
}
}和
namespace Assets
{
public class Asset : BaseAsset
{
// Code here
}
}我有一个从数据库返回资产集合的函数,我希望另一个函数执行该函数并返回一个BaseAsset集合。我已经尝试过了:
public static Collection<BaseAsset> GetCategoryAssets(int CategoryId, string UserId, string CompanyId)
{
return (Collection<BaseAsset>)AssetData.getAssets(CategoryId, UserId, CompanyId);
}但正如你所猜到的,它不起作用。如果我使用列表,我可以这样做:
public static List<BaseAsset> GetCategoryAssets(int CategoryId, string UserId, string CompanyId)
{
return AssetData.getAssets(CategoryId, UserId, CompanyId).Cast<BaseAsset>().ToList();
}但我更喜欢使用集合,有谁能想出一个优雅的解决方案吗?
干杯,r3plica
发布于 2013-01-01 00:58:54
这是一个非常常见的问题。您需要的特征的名称是通用协方差;也就是说,“如果长颈鹿是一种动物,那么长颈鹿列表就是一种动物列表”的特征。
问题是长颈鹿的名单并不是动物的名单。您可以将老虎放入动物列表,但不能将老虎放入长颈鹿列表,因此长颈鹿列表不能用于需要动物列表的任何上下文中。
应该使用IEnumerable<T>而不是Collection<T>的原因是,从C# 4开始,如果提供的类型参数都是引用类型,IEnumerable<T>在T中是协变的。也就是说,字符串序列可以用作对象序列,因为两者都是引用类型。但是int序列不能用作对象序列,因为其中一个是值类型。
之所以安全,是因为无法将老虎插入到IEnumerable<Giraffe>__中。
发布于 2012-12-31 23:03:49
如果您想要.ToList的易用性,只需编写您自己的.ToCollection扩展方法。实现应该很简单--获取一个IEnumerable<T>,循环遍历它,并使用Add将所有内容添加到一个集合中。
发布于 2012-12-31 23:04:47
问题是Collection<T>和ICollection<T>是不变的(也就是说,Collection<BaseAsset>既不是Collection<Asset>的子类型,也不是父类型)。
通过返回IEnumerable<BaseAsset>或IReadOnlyList<BaseAsset>而不是Collection<BaseAsset>,这个问题将很容易解决。
也就是说,你可以这样写:
public static IEnumerable<BaseAsset> GetCategoryAssets(int CategoryId, string UserId, string CompanyId)
{
return AssetData.getAssets(CategoryId, UserId, CompanyId);
}造型就变得不必要了。
通常,在指定返回值和函数参数时,您应该首选接口类型(如IList<T>、IReadOnlyList<T>、ICollection<T>或IEnumerable<T>),而不是具体类型(Collection<T>或List<T>)。
https://stackoverflow.com/questions/14103082
复制相似问题