diego_questions
diego_questions

Reputation: 13

Lists that implement an Interface, and passing a reference to that list

I have several different lists of objects, ie

List<Character> characters;
// ...

and some of those lists are of objects that implement the same interface:

public interface IDebugPrints
// ...

public class Character : IDebugPrints
// ...

I have a class where I would like to store a reference to a list (passed to it in its constructor) that implements IDebugPrints, ie

List<IDebugPrints> inList 

So that later I can iterate through that list (in this case to print out debug information about the current entries in the original List).

I can't figure out how to do this. If I pass the List as IEnumerable, it makes a copy of the original list, which dosent work for me since objects are added and removed from the original list after that copy.

Any help is appreciated. I have a feeling this isnt possible based on a few other questions here on SO, but would appreciate confirmation.

EDIT:

Here is a bit more pseudo code:

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

This last line gives compile errors:

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

Upvotes: 1

Views: 109

Answers (3)

Scott Nimrod
Scott Nimrod

Reputation: 11595

This compiles:

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

Upvotes: -1

Jeroen van Langen
Jeroen van Langen

Reputation: 22038

It isn't possible to cast a List<x> to a List<y> directly, unless you're using casting methods like: List<x> listX = listY.Cast<x>();

I would pass the List<Character> as an IList to the StoreList. With the .OfType<>() extension, you can iterate the childs of the type given. This way, the list isn't copied.

This way your StoreList can iterate it, not depending on the types you passed, as long the items are inherited from IDebugPrint, the ShowAllInfo will show the Info.

Here's an example:

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

Upvotes: -1

usr
usr

Reputation: 171178

Pass List<Character> characters as a IEnumerable<IDebugPrint>. This works beginning with C# 4.

Make internalList and inList typed as IEnumerable<IDebugPrint>.

Reference types are never copied in C# (except if explicitly implemented and requested by the programmer). .NET has no general way to copy an arbitrary reference type instance.

This means that your variables of type IEnumerable<IDebugPrint> will refer to the existing modifiable list.

Upvotes: 3

Related Questions