Bryan
Bryan

Reputation: 3494

Specify Generic type and interface

I need to have a list where all items extend class A and implement interface I. Additionally class A might be multiple parents up in the hierarchy.

If all the classes were direct descendants of class A I could just use an Abstract class that implements I as the generic and use that, but my use case doesn't allow for this.

is there a way to tell a List that its elements must both extend class A and implement interface I ? List<A,I> ? If not is there another way around this?

Example Code:

public class A
{
    // Class belongs to a third party library
}

public class B : A
{
    // Class belongs to a third party library
    public string Text{ get; set; }
}

public class C : A
{
    // Class belongs to a third party library
    public string Other{ get; set; }
}

interface I
{
    // Belongs to me
    bool shouldSend();
    string getName();
    string getValue();
}

public class MyClass : B, I 
{
      public string Name{ get; set; }

      public function myClass(ObjectWithName obj)
      {
           Name = obj.Name;
      }

      public string getValue()
      {
          return Text;
      }

      public bool shouldSend()
      {
          return true;
      }
}

public class MyClass2 : C, I 
{
      public string Name{ get; set; }

      public function myClass(ObjectWithName obj)
      {
           Name = obj.Name;
      }

      public string getValue()
      {
          return Other;
      }

      public bool shouldSend()
      {
          return true;
      }
}

public class mainActions
{
    // Here is where I need the list to use both restrictions
    public List<A,I> myList;
    // The class I need to use these things in
    public function mainActions(List<ObjectWithName> elements)
    {
        ThirdPartyCollection TPC = new ThirdPartyCollection();
        foreach(var el in elements)
        {
            MyList.Add(new MyClass(el));
            MyList.Add(new MyClass2(el));
            // TPC.Add accepts implementations of A here
            TPC.Add(MyList.ElementAt(MyList.Count - 1));
            TPC.Add(MyList.ElementAt(MyList.Count - 2));
        }


    }

    public function doThisLater()
    {
        foreach(var el in myList)
        {
            if(el.shouldSend())
            {
                // I need an implementation of I here
                doSomethingElse(el.getName(), el.getValue());
            }
        }
    }
}

EDIT: For anyone coming in search of an answer here in the future, it doesn't seem to be possible. Instead I used @servys answer and made a new list to hold my sub class objects:

public class MyList<T> : List<T> where T : A, I
{
}

Then I kept different lists for each subclass:

protected MyList<MyClass> MCList = new MyList<MyClass>();
protected MyList<MyClass2> MCList2 = new MyList<MyClass2>();

Upvotes: 0

Views: 77

Answers (1)

Servy
Servy

Reputation: 203850

When you specify generic constraints you can specify as many as you want, and all of them must be met, so you can simply add a generic constraint of A and I to your type, and a type has to meet both of those constraints to be a valid generic argument.

public class ClassThatNeedsABetterName<T> : List<T>
    where T : A, I
{ }

Upvotes: 4

Related Questions