一系列重载方法的替代方案

时间:2010-07-29 11:17:18

标签: c# .net generics overloading

我有一个帮助类,它在一个实体列表上执行一个简单但重复的过程。为简单起见,就像这样......

public static List<MyType> DoSomethingSimple(List<MyType> myTypes) {
    return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}

我现在需要添加对另一种类型的支持,但一切都是相同的...我如何避免增加这样的重载方法列表:

public static List<MyType> DoSomethingSimple(List<MyType> myTypes) {
    return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
}

public static List<MyOtherType> DoSomethingSimple(List<MyOtherType> myOtherTypes) {
    return myOtherTypes.Where(myOtherType => myOtherType.SomeProperty.Equals(2)).ToList();
}

......等等。

2 个答案:

答案 0 :(得分:4)

以下是两种方式:

  1. 使用泛型和公共基类
  2. 使用接口
  3. 方法1:

    public class BaseClass
    {
        public int SomeProperty { get; set; }
    }
    
    public class MyType : BaseClass { }
    public class MyOtherType : BaseClass { }
    
    public class ClassWithMethod
    {
        public static List<T> DoSomethingSimple<T>(List<T> myTypes)
            where T : BaseClass
        {
            return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
        }
    }
    

    方法2:

    public interface ICommon
    {
        int SomeProperty { get; set; }
    }
    
    public class MyType : ICommon
    {
        public int SomeProperty { get; set; }
    }
    
    public class MyOtherType : ICommon
    {
        public int SomeProperty { get; set; }
    }
    
    public class ClassWithMethod
    {
        public static List<T> DoSomethingSimple<T>(List<T> myTypes)
            where T : ICommon
        {
            return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
        }
    }
    

    现在,如果你试图让方法直接使用界面,就像这样:

    public class ClassWithMethod
    {
        public static List<ICommon> DoSomethingSimple(List<ICommon> myTypes)
        {
            return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
        }
    }
    

    如果您在调用时有List<ICommon>,那么这将有效,但如果您有List<MyType>则无效。在C#4.0中,如果我们稍微改变方法,可以这样做:

    public class ClassWithMethod
    {
        public static List<ICommon> DoSomethingSimple(IEnumerable<ICommon> myTypes)
        {
            return myTypes.Where(myType => myType.SomeProperty.Equals(2)).ToList();
        }
    }
    

    请注意,我改为使用IEnumerable<ICommon>代替。这里的概念被称为协变量和反变量,除此之外我不会说太多。搜索Stack Overflow以获取有关该主题的更多信息。

    提示:我会将输入参数更改为IEnumerable<T>,因为这会使您的方法在更多实例中可用,您可以使用不同类型的集合,数组等。只要它们包含正确的类型,就可以将它们传递给方法。通过将自己限制为List<T>,您可以强制代码的用户在某些情况下转换为列表。我的指南在输入参数中尽可能不具体,并且在输出参数中尽可能具体。

答案 1 :(得分:2)

假设该属性对于每个列表类型具有相同的名称和类型,您可以添加包含该属性的接口,并为要在此方法上调用此方法的每个类型实现该属性:

public interface ISomeProperty
{
    object SomeProperty { get; }
}

DoSomethingSimple可以是:

public static List<T> DoSomethingSimple<T>(IEnumerable<T> list) where T : ISomeProperty
{
    return list.Where(i => i.SomeProperty.Equals(2)).ToList();
}