【问题标题】:Extension Method for a Collection of Derived Types with Base Type in Method Signature方法签名中具有基类型的派生类型集合的扩展方法
【发布时间】:2011-07-22 15:21:56
【问题描述】:

我想为使用基类作为类型要求的对象集合编写扩展方法。我知道这不一定是做事的最佳方式,但我很好奇,因为我有兴趣学习语言的细微差别。这个例子解释了我想做的事情。

public class Human { public bool IsHappy { get; set; } }
public class Man : Human { public bool IsSurly { get; set; } }
public class Woman : Human { public bool IsAgreeable { get; set; } }

public static class ExtMethods
{
    public static void HappinessStatus(this IEnumerable<Human> items)
    {
        foreach (Human item in items)
        {
            Console.WriteLine(item.IsHappy.ToString());
        }
    }
}

// then in some method, I wish to be able to do the following

List<Woman> females = RetreiveListElements(); // returns a list of Women
females.HappinessStatus(); // prints the happiness bool from each item in a collection

我可以让扩展方法公开的唯一方法是创建人类集合。只要我只引用基类型的成员,是否可以在派生类型上调用这种类型的扩展方法?

【问题讨论】:

  • 它适用于 .Net 4,但不适用于早期版本。问题上的标签说 c#3.0

标签: c# .net oop inheritance c#-3.0


【解决方案1】:

您的代码实际上将使用 C# 4 编译器按原样编译,因为该版本支持 contravariant type parameters

要使其与 C# 3 一起使用,您可以为 IEnumerable&lt;T&gt; 创建一个泛型扩展方法,该方法具有作用于泛型类型的where T : Human 约束,而不是专门针对IEnumerable&lt;Human&gt;

public static void HappinessStatus<T>(this IEnumerable<T> items) where T : Human
{
    foreach (T item in items)
    {
        Console.WriteLine(item.IsHappy.ToString());
    }
}

然后您可以按照您的描述调用 List&lt;Woman&gt; 集合上的扩展方法。

【讨论】:

  • 这确实有效,但我创建了一个通用的字符串列表,这个方法将自己暴露给一个字符串列表。有没有办法只在使用 Human 的集合或 Human 的派生类型时才公开此方法?
  • @Nate:我不这么认为。无论哪种情况,您问题中的代码和我的答案都有效(我也刚刚测试了您的问题代码),如果您尝试在非人类列表中调用它,两者都不会编译。
  • 我现在明白为什么很多人反对这种类型的扩展方法,在无法编译的集合上公开方法是一种糟糕的形式。
  • @Nate:我的错,如果编译为 C# 4.0,您问题中的代码可以工作。它不会编译为 C# 3.0。具有讽刺意味的是,因为我写了我的答案知道您正在寻找 3.0 解决方案...
  • @Nate - “我创建了一个通用的字符串列表,这个方法将自己暴露给一个字符串列表”
猜你喜欢
  • 2023-04-09
  • 2019-08-23
  • 1970-01-01
  • 2019-05-16
  • 2016-04-11
  • 2014-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
相关资源
最近更新 更多