gpt4 book ai didi

c# - 反方差的常见编程用途是什么?

转载 作者:可可西里 更新时间:2023-11-01 18:37:51 26 4
gpt4 key购买 nike

我已阅读以下关于反方差的帖子和 Lasse V. Karlsen 的回答:

Understanding Covariant and Contravariant interfaces in C#

虽然我理解这个概念,但我不明白它为什么有用。例如,为什么有人会制作一个只读列表(如帖子中:List<Fish> fishes = GetAccessToFishes(); // for some reason, returns List<Animal>)

我也知道覆盖方法的参数可以是反变的(概念上。据我所知,这在 C#、Java 和 C++ 中没有使用)。有哪些例子表明这是有道理的?

我会很感激一些简单的现实世界的例子。

最佳答案

(我认为这个问题更多的是关于协方差而不是逆变,因为引用的例子与协方差有关。)

List<Fish> fishes = GetAccessToFishes(); // for some reason, returns List<Animal>

断章取义,这有点误导。在您引用的示例中,作者打算从技术上传达这样的想法,如果 List<Fish>实际上是在引用 List<Animal>添加一个 Fish 将是安全的给它。

当然,这也可以让您添加 Cow对它 - 这显然是错误的。

因此编译器不允许您分配 List<Animal>引用 List<Fish>引用。

那么什么时候这才是真正安全且有用的呢?

如果集合不能被修改,这是一个安全的赋值。在 C# 中,一个 IEnumerable<T>可以表示一个不可修改的集合。

所以你可以安全地做到这一点:

IEnumerable<Animal> animals = GetAccessToFishes(); // for some reason, returns List<Animal>

因为不可能将非 Fish 添加到 animals .它没有允许您这样做的方法。

那么这什么时候有用?

当您想要访问集合的某些通用方法或属性时,这很有用,该集合可以包含从基类派生的一种或多种类型的项目。

例如,您可能有一个层次结构来表示超市不同类别的库存。

假设基类StockItem , 有一个属性 double SalePrice .

我们还假设您有一个方法,Shopper.Basket()返回 IEnumerable<StockItem>代表购物者购物篮中的商品。篮子中的元素可以是来自 StockItem 的任何具体类型.

在这种情况下,您可以添加购物篮中所有商品的价格(我在没有使用 Linq 的情况下简单地写了这个来弄清楚发生了什么。真正的代码当然会使用 IEnumerable.Sum()):

IEnumerable<StockItem> itemsInBasket = shopper.Basket;

double totalCost = 0.0;

foreach (var item in itemsInBasket)
totalCost += item.SalePrice;

逆变

逆变的一个例子是当你想通过基类类型对一个项目或项目集合应用一些 Action 时,即使你有一个派生类型。

例如,您可以使用一种方法对 StockItem 序列中的每个项目应用操作像这样:

void ApplyToStockItems(IEnumerable<StockItem> items, Action<StockItem> action)
{
foreach (var item in items)
action(item);
}

使用 StockItem例如,假设它有一个 Print()您可以使用该方法将其打印到收银台收据上。你可以像这样调用然后使用它:

Action<StockItem> printItem = item => { item.Print(); }
ApplyToStockItems(shopper.Basket, printItem);

在此示例中,购物篮中的商品类型可能是 Fruit , Electronics , Clothing等等。但是因为它们都来自 StockItem ,代码适用于所有这些。

希望这种代码的用途是明确的!这与 Linq 中许多方法的工作方式非常相似。

关于c# - 反方差的常见编程用途是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19475577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com