2015-01-18 3 views
1

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

List<Character> characters; 
// ... 

и некоторые из этих списков являются объекты, которые реализуют один и тот же интерфейс:

public interface IDebugPrints 
// ... 

public class Character : IDebugPrints 
// ... 

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

List<IDebugPrints> inList 

Так что позже я могу выполнить итерацию по этому списку (в этом случае распечатать отладочную информацию о текущих записях в первоначальном списке).

Не могу понять, как это сделать. Если я передаю List как IEnumerable, он делает копию исходного списка, который доцент работает для меня, так как объекты добавляются и удаляются из исходного списка после этой копии.

Любая помощь приветствуется. У меня такое чувство, что это невозможно по нескольким другим вопросам здесь, но это было бы приятно.

EDIT:

Вот немного больше псевдо-код:

public interface IDebugPrints 
// ... 

public class Character : IDebugPrints 
// ... 

public class StoreList 
{ 
    private List<IDebugPrints> internalList; 

    public StoreList(List<IDebugPrints> inList) 
    { 
     internalList = inList; 
    } 
} 

// The I have the various lists, for example 
List<Character> characters; 

// ... 

// And I want to pass that list 
StoreList sl = new StoreList(characters); 

Последняя строка дает ошибки компиляции:

Cannot convert from System.Collections.Generic.List<Character> to Systems.Collections.Generic.List<IDebugPrints> 
+4

Пропустите список как List . Почему это не работает? Кроме того, даже если он передан как IE , копия не будет выполнена. В .NET никогда не существует неявной копии объекта ссылочного типа. – usr

+0

Не могли бы вы предоставить больше кода и объяснить, что именно ваша проблема? –

+0

Несомненно, отредактировал оригинальный пост с более подробной информацией. Конкретная проблема: я работаю над игрой с различными списками объектов. Я бы хотел, чтобы общий способ сбросить содержимое этих списков на консоль отладки с помощью команды консоли. Поэтому у меня есть классы, которые я хочу сбрасывать с помощью IDebugPrints. А затем класс, который выполняет итерацию над списком и вызывает метод из IDebugPrints. –

ответ

-1

компилируется:

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 
using System.Collections.Generic; 

public interface IDebugPrints 
{ 

} 

public class Character : IDebugPrints 
{ 

} 

public class StoreList 
{ 
    private List<IDebugPrints> internalList; 

    public StoreList(List<IDebugPrints> inList) 
    { 
     internalList = inList; 
    } 
} 

[TestClass] 
public class Test1 
{ 
    [TestMethod] 
    public void MyTest() 
    { 
     var characters = new List<IDebugPrints>(); 
     characters.Add(new Character()); 
     var sl = new StoreList(characters); 
    } 
} 
+0

Вы пробовали это. Это все еще дает ошибки. –

+0

Вы не инициализировали символы перед передачей. Я обновил код, который компилируется. –

+0

Как он будет создавать экземпляр переменной 'characters'? –

3

Pass List<Character> characters как IEnumerable<IDebugPrint>. Эта работа начинается с C# 4.

Сделайте internalList и inList, набрав как IEnumerable<IDebugPrint>.

Ссылочные типы никогда не копируются в C# (кроме случаев, когда они явно реализованы и запрошены программистом). У .NET нет общего способа копирования экземпляра произвольного ссылочного типа.

Это означает, что ваши переменные типа IEnumerable<IDebugPrint> будут ссылаться на существующий модифицируемый список.

+0

Спасибо. Это то, что я изначально сделал, однако была ошибка в другом разделе кода, который заставлял меня думать, что произошла копия. Было 4 утра :) Я должен был просто ложиться спать и быстро решил бы это по утрам :) –

+1

Я думаю, что это приятное решение, я не знал, что с C# 4 он смог создать «Список < > 'в' IEnumerable '. Преимущество этого решения заключается в том, что StoreList не знает, что IEnumerable является списком. Кроме того, «StoreList» не нужно (не разрешено) добавлять/удалять элементы. Tnx для обмена. –

-1

Это не представляется возможным бросить List<x> к List<y> непосредственно, если вы не используете методы литья, как: List<x> listX = listY.Cast<x>();

Я бы передать List<Character> как IList к магазинДобавить. С расширением .OfType<>() вы можете перебирать дочерние элементы данного типа. Таким образом, список не копируется.

Таким образом, ваш StoreList может перебирать его, а не в зависимости от типа вы прошли, пока элементы унаследованы от IDebugPrint, то ShowAllInfo покажет Info.

Вот пример:

public interface IDebugPrints 
{ 
    string Info { get; set; } 

    void ShowInfo(); 
} 

public class Character : IDebugPrints 
{ 
    public string Info {get;set;} 

    public void ShowInfo() 
    { 
     Console.WriteLine(Info); 
    } 
} 

public class StoreList 
{ 
    private IList internalList; 

    public StoreList(IList inList) 
    { 
     internalList = inList; 
    } 

    public void ShowAllInfo() 
    { 
     // I love the OfType<>() extension, it only returns the items of type IDebugPrints. 
     foreach (var item in internalList.OfType<IDebugPrints>()) 
      item.ShowInfo(); 
    } 

} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Character> characters = new List<Character>(); 

     characters.Add(new Character { Info = "Character 1" }); 
     characters.Add(new Character { Info = "Character 2" }); 

     // And I want to pass that list 
     StoreList sl = new StoreList(characters); 


     sl.ShowAllInfo(); 

     Console.ReadKey(); 
    } 
} 
+0

См. Мое решение. –

+0

Это напомнило мне изучить использование IList вместо класса concete. TY! –

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