Альтернатива серии перегруженных методов - PullRequest
1 голос
/ 29 июля 2010

У меня есть вспомогательный класс, который выполняет простой, но повторяющийся процесс в Списке сущностей. Для простоты это так ...

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 ]

4 голосов
/ 29 июля 2010

Вот два способа:

  1. Использовать обобщенные значения и общий базовый класс
  2. Использовать интерфейсы

Метод 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>.Понятие здесь называется ко- и противоречивостью, и помимо этого я не буду много говорить об этом.Search Stack Overflow для получения дополнительной информации о предмете.

Совет : я бы изменил входной параметр на IEnumerable<T> независимо, так как это сделает ваш метод пригодным для использования в большем количестве случаев, вы могли быимеют разные типы коллекций, массивов и т. д. и если они содержат правильный тип, они могут быть переданы методу.Ограничивая себя List<T>, вы заставляете пользователя своего кода преобразовывать в список в некоторых случаях.Мои рекомендации должны быть как можно более точными во входных параметрах и как можно более точными в выходных параметрах.

2 голосов
/ 29 июля 2010

Предполагая, что свойство имеет одинаковые имя и тип для каждого типа списка, вы можете добавить интерфейс, содержащий свойство, и реализовать его для каждого типа, для которого вы хотите вызвать этот метод:

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();
}
...