Okay so I'm having a bit of trouble getting some interfaces to work. Basically I have an interface (A) and within that interface there is a property IEnumerable, where T is another interface (B). I have a bunch of entity framework models, some will implement A and others implement B. The models that implement A will have an IEnumerable where T is an implementation of B. I then have a bunch of methods I need to write that take A as a parameter and use the concrete implementation of B contained within the IEnumerable. The first, and most obvious attempt, looked like this:
public interface IA {
public IEnumerable<B> BEnum {get; set;}
}
public interface IB {
public string foo {get; set;}
public int boo {get; set;}
}
public class ModelA : IA {
public IEnumerable<ModelB> BEnum {get; set;}
}
public class ModelB : IB {
public string foo {get; set;}
public int boo {get; set;}
}
Except this doesn't work. In this attempt I get CS0738 because ModelA doesn't match the return type of the interface, which is fair enough. I tried reworking it like so:
public interface IA<T> where T: IB {
blah
}
public class ModelA : IA<ModelB> {
blah
}
And it looked like this was working except I can't figure out a way to get a method to accept IA as a parameter. Is this possible?
CodePudding user response:
You can add a type constraint
public interface IA<T>
where T : IB
{
IEnumerable<T> BEnum { get; set; }
}
public interface IB
{
public string foo { get; set; }
public int boo { get; set; }
}
Now, an implementing class can declare
// Tested and works!
public class ModelA : IA<ModelB>
{
public IEnumerable<ModelB> BEnum { get; set; }
}
public class ModelB : IB
{
public string foo { get; set; }
public int boo { get; set; }
}
where B
must implement IB
. The advantage is that the interface does only need to know about other interfaces, but not about implementations.
However, it could be of an advantage to hard code the type as the interface type. This enables you to program against the interface without having to worry about concrete types.
public interface IA
{
IEnumerable<IB> BEnum { get; set; }
}
CodePudding user response:
You can definetly have IA as a parameter of a method. Otherwise you can use generic methods. Here are some examples :
public class Foo
{
public void Method(IA<IB> obj)
{
/* Do something */
}
public void GenericMethod_1<TB>(IA<TB> obj)
where TB : ModelB
{
/* Do something */
}
public void GenericMethod_2<TA>(TA obj)
where TA : ModelA
{
/* Do something */
}
}
Method
is the most general case where the method accepts any object implementing IA with any IB. The first generic method, GenericMethod_1
, allows you to constraint the expected type T : IB
that is used for IA. The second generic method, GenericMethod_2
, accepts ModelA and any object derived from it.