1

这里有另一个简单的问题让我难以理解。

我有 2 节课:

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

4

5 回答 5

11

这是一个非常常见的问题。您想要的功能名称是通用协方差;也就是说,“如果长颈鹿是一种动物,那么长颈鹿列表就是动物列表”的特征。

问题是长颈鹿列表不是动物列表。您可以将老虎放入动物列表中,但不能将老虎放入长颈鹿列表中,因此在任何需要动物列表的上下文中都不能使用长颈鹿列表。

您应该使用的原因IEnumerable<T>Collection<T>因为从 C# 4 开始,IEnumerable<T>在 T 中是协变的,前提是提供的类型参数都是引用类型。也就是说,字符串序列可以用作对象序列,因为两者都是引用类型。但是整数序列不能用作对象序列,因为一个是值类型。

这是安全的原因是因为没有办法将老虎插入IEnumerable<Giraffe>.

于 2012-12-31T16:58:53.827 回答
2

如果您想要轻松.ToList,只需编写自己的.ToCollection扩展方法即可。实现应该很简单——通过一个IEnumerable<T>, 循环并将所有内容添加到一个集合中Add

于 2012-12-31T15:03:48.777 回答
1

问题在于Collection<T>andICollection<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>

于 2012-12-31T15:04:46.613 回答
0

与其尝试转换为基类,不如直接提取一个接口并使用它。

于 2012-12-31T15:04:25.870 回答
0

由于Collection<T>该类有一个以 aIList<T>作为参数的构造函数,因此您始终可以执行以下操作:

Collection<BaseAsset> = new Collection<BaseAsset>(
                                           assetList.Cast<BaseAsset>().ToList());

当然,如果你需要重用这个行为,你可以做一个 CastToCollection 扩展:

public static Collection<TResult> CastToCollection<TResult>(this IEnumerable source)
{
   return new Collection<TResult>(source.Cast<TResult>().ToList());
}
于 2012-12-31T21:13:50.550 回答