2010-07-29 11 views
1

J'ai une classe d'aide qui fait un processus simple mais répétitif sur une liste d'entités. Par souci de simplicité, il est comme ça ...Alternative à une série de méthodes surchargées

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

J'ai besoin maintenant d'ajouter le support pour un autre type, mais tout est identique ... Comment puis-je éviter une liste croissante des méthodes surchargées comme ceci:

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

... et ainsi de suite.

+0

"SomeProperty" est-il hérité d'une classe de base commune dans les deux cas? –

Répondre

4

est ici de deux façons:

  1. génériques d'utilisation, et une commune classe de base
  2. Utiliser les interfaces

Méthode 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(); 
    } 
} 

Méthode 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(); 
    } 
} 

Maintenant, si vous essayez de faire de la méthode utilisée par l'interface directement, comme ceci:

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

Ensuite, cela fonctionnerait si vous avez un List<ICommon> lorsque vous l'appelez, mais ne fonctionnera pas si vous avez un List<MyType>. En C# 4.0, cela peut se faire que si l'on change la méthode légèrement:

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

Notez que j'ai changé à l'aide d'un IEnumerable<ICommon> à la place. Le concept ici est appelé Co- et contre-variance, et au-delà je ne vais pas en dire beaucoup à ce sujet. Rechercher Stack Overflow pour plus d'informations sur le sujet.

Conseil: Je changerais le paramètre d'entrée pour être IEnumerable<T> peu importe, car cela rendrait votre méthode utilisable dans des instances plus, vous pourriez avoir différents types de collections, tableaux, etc., et aussi longtemps qu'ils contiennent le droit type, ils peuvent être passés à la méthode. En vous limitant à List<T> vous forcez l'utilisateur de votre code à convertir dans une liste dans certains cas. Mes directives doivent être aussi peu spécifiques que possible dans les paramètres d'entrée, et aussi spécifiques que possible dans les paramètres de sortie.

2

En supposant que la propriété a le même nom et le type pour chaque type de liste, vous pouvez ajouter une interface contenant la propriété et la mettre en œuvre pour chaque type que vous voulez appeler cette méthode sur:

public interface ISomeProperty 
{ 
    object SomeProperty { get; } 
} 

DoSomethingSimple pourrait alors être:

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