2014-10-28 3 views
1

У меня есть несколько различных типов все с общим свойством:C# Метод взять список типов с тем же свойством

public class A { 
    public int SomeCommonProperty { get; set; } 

    /* 
    * some other stuff 
    */ 
} 

public class B { 
    public int SomeCommonProperty { get; set; } 

    /* 
    * some other stuff 
    */ 
} 

Я хочу иметь метод, который принимает список любого из этих объектов с этим свойством так что я могу перебирать список и сравните это свойство с другим параметром как:

public static List<T> MethodToTakeListOfAboveTypes<T>(this List<T> destinationList, List<T> sourceList, string someProp) 
{ 
    if (sourceList != null && sourceList.Exists(tab => tab.SomeCommonProperty == someProp)) 
    { 
    destinationList = sourceList.Where(tab => tab.SomeCommonProperty == someProp).ToList(); 
    } 
    return destinationList; 
} 

Приведенный выше код не работает, как T не имеет определение «SomeCommonProperty», который имеет смысл. Я хочу просто передать более общий объект с этим свойством, так что мне не нужно создавать этот же метод для каждого типа. Я просто не могу получить синтаксис правильно. Имеет ли это смысл?

Я знаю, что я должен поместить поле SomeCommonProperty в базовый класс и наследовать, но по какой-то причине это не работает.

+2

Наследование специально предназначено для решения этой проблемы. Почему вы думаете, что это «похоже, не работает»? –

ответ

2

Я знаю, что я должен поместить поле SomeCommonProperty в базовый класс и наследовать, но по какой-то причине это не работает.

Вы должны добавить родовое ограничение, то он будет работать нормально

where T : CommonType 
4

сделать все классы реализовать некоторый интерфейс (или наследует это свойство от некоторого базового класса), например,

public interface ICommonInterface 
{ 
    int SomeCommonProperty { get; set; } 
} 

Затем вы можете поместить интерфейс/класс ограничение на общий тип параметра:

public static List<T> MethodToTakeListOfAboveTypes<T>(   
    this List<T> destinationList, List<T> sourceList, string someProp) 
    where T: ICommonInterface 
{ 
    // ... 
} 

ПРИМЕЧАНИЕ: Вы можете избежать проверки, если любой элемент с someProp существует в источнике (в худшем случае вам придется перечислить sourceList дважды). Просто сделать фильтрацию и проверить, есть ли какие-либо результаты

public static List<T> MethodToTakeListOfAboveTypes<T>(
    this List<T> destinationList, List<T> sourceList, string someProp) 
    where T: ICommonInterface 
{ 
    if (sourceList == null) 
     return destinationList; 

    var filtered = sourceList.Where(s => s.SomeCommonProperty == someProp).ToList(); 
    return filtered.Any() ? filtered : destinationList; 
} 
+0

Это, вероятно, лучший подход к использованию наследования, а не к интерфейсу + метод расширения в этом случае. –

1

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

public static List<T> MethodToTakeListOfAboveTypes<T>(this List<T> destinationList, List<T> sourceList, string someProp) where T : BaseClass 

Обратите внимание на использование where T :, который на самом деле говорит T должен получить от ...

Заменить BaseClass с действительным именем базового класса.

public class BaseClass 
{ 
    public string SomeCommonProperty { get; set; } 
} 
1

Создайте интерфейс с этим свойством, что каждый класс реализует, а затем добавить ограничение на ваш общий метод:

public interface ICommonProperty 
{ 
    int SomeCommonProperty {get;set;} 
} 

public class A : ICommonProperty 
{ 
    public int SomeCommonProperty { get; set; } 
} 

public class B : ICommonProperty 
{ 
    public int SomeCommonProperty { get; set; } 
} 

public static List<T> MethodToTakeListOfAboveTypes<T>(this List<T> destinationList, List<T> sourceList, string someProp) where T : ICommonProperty 
0

Если вы можете пойти с наследованием (как вы говорите, вы можете), вы должны сделай это. Однако, если по какой-то причине вам нужно перебирать кучу объектов, которые не имеют источник и доступ к некоторым свойством, вы знаете, что они есть, вы можете использовать dynamic:

class foo 
{ 
    public string myProp = "foo"; 
} 

class bar 
{ 
    public string myProp = "bar"; 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     List<dynamic> list = new List<dynamic>(); 
     list.Add(new foo()); 
     list.Add(new bar()); 

     foreach (dynamic o in list) 
     { 
      Console.WriteLine(o.myProp); 
     } 
    } 
} 

Вы также можете вызвать произвольное методы на dynamic.Вы получаете исключение, если свойство/метод не существует.

Смежные вопросы