2009-03-16 1 views
0

У меня есть базовый класс LabFileBase. Я создал список и добавил к нему свои производные классы. Я хочу выполнить поиск в списке для определенного объекта на основе ключа, который я определил. Проблема, с которой я сталкиваюсь, заключается в том, как вы угасаете в выражении LINQ?Downcasting и Linq

Вот некоторые примеры код:

public abstract class LabFileBase 
{ 
} 

public class Sample1 : LabFileBase 
{  
    public string ID {get;set;} 
    public string Name {get;set;} 
    //.. 
} 

public class Sample2 : LabFileBase 
{  
    public string ID {get;set;} 
    public string Name {get;set;} 
    //.. 
} 

Я хочу найти конкретный тип Sample2, но мне нужен обратное приведение, если я использовал обычный цикл Еогеаспа так:

foreach(var s in processedFiles) //processedFiles is a List<LabFileBase> 
    if (s is Sample2) 
     var found = s as Sample2; 
      if (found.ID = ID && found.Name == "Thing I'm looking for") 
        //do extra work 

I скорее всего, было бы что-то вроде этого:

var result = processedFiles.Select(s => s.ID == SomeID && s.Name == SomeName); 

Возможно ли это, и какой синтаксический punctu или это foreach мой единственный вариант из-за разных объектов. В Sample1 и Sample2 только ID и Name имеют одинаковые поля.

EDIT: Спасибо всем за вашу поддержку и предложения, я ввел почти все в отставание для реализации.

ответ

5

Чтобы уточнить ответ Джона, OfType почти наверняка правильный оператор, если вы не готовы поставить эти поля в вашу базу класс. Например:

foreach(var s in processedFiles.OfType<Sample2>()) 
    if(s.ID == ID && s.Name == "Thing I'm looking for") 
     // whatever 

foreach(var s in processedFiles.OfType<Sample1>()) 
    if(s.ID == ID && s.Name == "Some other thing") 
     // and so on 
6

Почему бы не поставить ID и Name в базовый класс? Тогда вам не нужно ничтожество.

Если у вас есть do необходимо лить, операторы Cast и OfType могут быть вам полезны. Каждый преобразует последовательность в последовательность указанного типа: Cast предполагает, что каждый элемент равен правильный тип (и выбрасывает исключение, если это не так); OfType работает скорее как оператор C# as, возвращая только те элементы, которые являются правильными и игнорируют другие.

+0

seq.OfType () работает как seq.Where (эш => эль является MyFavType). – yfeldblum

+0

@Jon: Я обязательно рассмотрю перенос идентификатора и имени в базовый класс. Чем больше я думаю об этом, они действительно там. – Chris

+0

@Justice: Не совсем, потому что он * также * заканчивается последовательностью целевого типа. Это как seq.Where (...). Cast <...>() –

0

Интересный вопрос. В дополнение к Jon Skeet (который лучше, чем этот вариант) обратите внимание, что вы можете попробовать более ручную альтернативу. Добавьте дополнительное свойство, содержащее идентификатор для типа объекта.

public abstract class LabFileBase 
{ 
    public string LabFileObjectType { get; } 
    public string ID {get;set;} 
    public string Name {get;set;} 
} 


public class Sample1 : LabFileBase 
{  
    public string LabFileObjectType { get { return "Sample1"; } } 
    //.. 
} 

public class Sample2 : LabFileBase 
{  
    public string LabFileObjectType { get { return "Sample2"; } } 
    //.. 
} 

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

var result = processedFiles.Select(s => s.ID == SomeID && s.Name == SomeName && s.LabFileObjectType == "Sample2"); 
+0

Если вы хотите сделать тест в коде, почему бы просто не использовать «&& s is Sample1»? –

+0

Возможно, вы бы это сделали. Я говорю, что есть альтернатива из вашего примера. Это определенно более правильно. –