I am trying to find the right way to use a Generic List of Generic Interfaces as a variable.
Here is an example. It is probably not the best, but hopefully you will get the point:
public interface IPrimitive<T>
{
T Value { get; }
}
and then in another class, I want to be able to declare a variable that holds a list of objects that implement IPrimitive<T> for arbitrary T.
// I know this line will not compile because I do not define T
List<IPrimitive<T>> primitives = new List<IPrimitives<T>>;
primitives.Add(new Star()); // Assuming Star implements IPrimitive<X>
primitives.Add(new Sun()); // Assuming Sun implements IPrimitive<Y>
Note that the T in IPrimitive<T> could be different for each entry in the list.
Any ideas on how I could setup such a relationship? Alternative Approaches?
public interface IPrimitive
{
}
public interface IPrimitive<T> : IPrimitive
{
T Value { get; }
}
public class Star : IPrimitive<T> //must declare T here
{
}
Then you should be able to have
List<IPrimitive> primitives = new List<IPrimitive>;
primitives.Add(new Star()); // Assuming Star implements IPrimitive
primitives.Add(new Sun()); // Assuming Sun implements IPrimitive
John is correct.
Might I also suggest (if you are using C# 4) that you make your interface covariant?
public interface IPrimitive<out T>
{
T Value { get; }
}
This could save you some trouble later when you need to get things out of the list.
You say it won't work because you don't define T. So define it:
public class Holder<T>
{
public List<IPrimitive<T>> Primitives {get;set;}
}
This is one of the most complicated elements of the c# language though it is incredibly important for building well defined components. As such, c# falls short. However it is definitely possible to make this work.
The trick is to have 3 parts:
A non generic interface that contains all requirements of the interface.
A generic abstract class that implements the non generic interface and performs the type conversions as necessary.
A class that implements the generic abstract class with the appropriately typed results
For example:
public interface INonGenericInterface{
void Execute(object input);
object GetModel();
}
public abstract class IGenericInterfaceBase<T> : INonGenericInterface{
void INonGenericInterface.Execute(object input){
Execute((T) input);
}
object INonGenericInterface.GetModel(){
return GetModel();
}
protected abstract void Execute(T input);
protected abstract T GetModel();
}
public class ImplementingClass : IGenericInterfaceBase<ModelClass>{
protected override void Execute(ModelClass input){ /*Do something with the input */ }
protected override ModelClass GetModel(){ return new ModelClass();}
}
//Extras for demo
public class ModelClass { }
public class ModelClass2 { }
public class ImplementingClass2 : IGenericInterfaceBase<ModelClass2>
{
protected override void Execute(ModelClass2 input) { /*Do something with the input */ }
protected override ModelClass2 GetModel() { return new ModelClass2(); }
}
var agi = new INonGenericInterface[] { new ImplementingClass(), new ImplementingClass2() };
agi[0].Execute(); var model = agi[0].GetModel();
agi[1].Execute(); var model2 = agi[1].GetModel();
//Check the types of the model and model2 objects to see that they are appropriately typed.
This structure is incredibly useful when coordinating classes w/ one another because you're able to indicate that an implementing class will make use of multiple classes and have type checking validate that each class follows established type expectations. In addition, you might consider using an actual class instead of object for the non-generic class so that you can execute functions on the result of the various non-generic calls. Using this same design you can have those classes be generic classes w/ their own implementations and thus create incredibly complex applications.
To OP: Please consider changing the accepted answer to this to raise awareness of the correct approach as all previously stated answers fall short for various reasons and have probably left readers with more questions. This should handle all future questions related to generic classes in a collection.
Related
Intro
I am creating an ASP.NET Web API application with Entity Framework. What I need to do is return different representations of the same resource for one URI, depending on user role. For example, api/employees/1 will return two different objects for admin and standard user:
Standard user
public class EmployeeBasic
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Admin
public class EmployeeExtended : EmployeeBasic
{
public decimal Salary { get; set; }
}
The idea and the attempts
For each resource representation, I will need to provide some related classes, let's say Sort Models for example. I was wondering if it is possible to use generic types and inheritance to create a generic repository methods for related representations. I thought of the following way of doing this:
Create some base interface for Sort Models:
public interface ISortModel<out TBusinessEntity>
{
//
}
Create generic SortModel as a base type for all sort models
public abstract class SortModel<TDBEntity, TBusinessEntity> : ISortModel<TBusinessEntity>
{
// Database sorting
public abstract IQueryable<TDBEntity> ApplyToQuery(IQueryable<TDBEntity> query);
// Local sorting
public abstract IEnumerable<TBusinessEntity> ApplyToLocal(IEnumerable<TBusinessEntity> localList);
// ...
// Some private logic (expression mappers, etc.)
}
Create sort model for basic resource
public class EmployeeBasicSortModel : SortModel<DBModel.Employee, EmployeeBasic>
{
public int FullName { get; set; }
public override IQueryable<DBModel.Employee> ApplyToQuery(IQueryable<DBModel.Employee> query)
{
// implementation
}
public override IEnumerable<EmployeeBasic> ApplyToLocal(IEnumerable<EmployeeBasic> localList)
{
// implementation
}
}
Extend the basic sort model and add sorting for the extended resource properties
public class EmployeeExtendedSortModel : EmployeeBasicSortModel //, ... Is it possible to somehow do that?
{
public override IEnumerable<EmployeeExtended> ApplyToLocal(IEnumerable<EmployeeExtended> localList)
{
var partiallyOrderedList = base.ApplyToLocal(localList);
// Add extended sorting
}
// ... ?
}
Use the above classes to create generic service:
class EmployeesService()
{
public IList<TEmployee> GetAll<TEmployee>(ISortModel<TEmployee> sortModel)
where TEmployee : BasicEmployee
{
// implementation
}
}
The problem
When I thought about it for the first time, it seemed pretty simple. But when I started implementing this, I couldn't figure out the way to implement Step 4. Either I am missing something in my C# knowledge (which is quite possible) or this is not possible in the way I am trying to do this.
So the question is: can I create a base class with generic type, derive from it with basic resource as a type and derive one more time with the extended class?
Holy goodness this is a complicated question. The generics are a huge red herring. Ignore the generics; the problem is more fundamental. Let's simplify it greatly.
class Animal {}
class Mammal : Animal {}
class Tiger : Mammal {}
class Shape {}
class Square : Shape {}
class GreenSquare : Square {}
class B
{
public virtual Mammal Frob(Square s) { ... }
}
class D : B
{
public override SomeReturnType Frob(SomeArgumentType m) { ... }
}
The question is: what are legal return and argument types for this virtual override?
The answer is: in C# the only legal types are those that exactly match the overridden method's types. An override of Frob must return Mammal and take Square.
Now, we could in theory make it typesafe for D.Frob to return Tiger. Do you see why? If we have a D converted to B, then it returns a Tiger, but a Tiger is an Animal, so we're OK.
This feature is called return type covariance, and it has been suggested for C# for, oh, some 15 years now, and has never been implemented. It is not supported by the CLR, and it is not a high priority for the design team, and it creates new flavours of the Brittle Base Class Problem, and all these are such points against that it is unlikely to meet the bar any time soon.
C++ does support this feature, including on the CLR, so it is possible to do on the CLR. You just end up having to generate a bunch of helper methods.
Of course we cannot have D.Frob return Animal. It could return a Turtle, but B.Frob promises to only return Mammals.
What about the argument type? It could be typesafe to have D.Frob take Shape. Again, same reasoning: if we have a D converted to B then we will only get squares. But it would not be safe to have D.Frob take a GreenSquare, because B.Frob promises to be able to take any square, not just green squares.
This feature is called formal parameter type contravariance and few languages implement it.
Now, you want return type covariance and formal parameter type covariance, which is neither supported nor typesafe. Interestingly enough, Eiffel supports this kind of covariance.
C# developers who want return type covariance usually end up doing something like:
class D : B {
private Tiger FrobPrivate(Square s) { ... }
public override Mammal Frob(Square s)
{
return this.FrobPrivate(s);
}
public new Tiger Frob(Square s)
{
return this.FrobPrivate(s);
}
}
Which is basically what the C# compiler would have to do on your behalf to implement the feature anyways.
I'm writing an SDK which has an OOP structure for implementing data types;
first an interface
then an abstract implementation
finally an abstract generic implementation
People can choose to implement either the interface, or derive from either of the classes.
public interface IGoo
{
IGoo Duplicate();
...
}
public abstract class Goo : IGoo
{
IGoo IGoo.Duplicate() {
return Duplicate();
}
abstract public Goo Duplicate();
...
}
public abstract class Goo<T> : Goo
{
abstract public Goo<T> Duplicate(); ??????
...
}
I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.
Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?
What about the following?
public interface IObj
{
IObj Duplicate();
}
public abstract class Obj : IObj
{
public Obj()
{
}
public virtual IObj Duplicate()
{
return this;
}
}
public abstract class ObjT<T> : Obj
{
public ObjT()
{
}
public override IObj Duplicate()
{
return this;
}
}
public class ObjImpl : Obj
{
}
public class ObjTImpl : ObjT<int>
{
}
I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
ObjImpl a = new ObjImpl();
ObjTImpl b = new ObjTImpl();
Console.WriteLine(a.Duplicate().GetType());
Console.WriteLine(b.Duplicate().GetType());
Console.ReadLine();
}
}
}
// outputs:
// ObjImpl
// ObjTImpl
The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.
Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.
There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol
It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.
public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.
I'm approaching a problem while still having some ignorance regarding Generics and their proper declarations / uses. I get the premiss, but some of the ins-n-outs of generics still elude me.
Given the following code (does not compile and contains code-smell):
public interface IUIConcern<out T> where T : IUIConcernExtension
{
string Name { get; }
Func<T> Extend();
}
public class UIConcern
{
public static void Register<T>(string concernName, IUIConcern<T> uiConcern) where T : IUIConcernExtension
{
Concerns.Add(uiConcern);
}
public static List<IUIConcern<T>> Concerns{
get {
// Logic...
}
set {
// Logic...
}
}
}
... I have a few questions:
Why do I have to specify this part public static void Register<T>(string concernName, IUIConcern<T> uiConcern) where T : IUIConcernExtension
with a constraint when I have already constrained the T in the declaration public interface IUIConcern<out T> where T : IUIConcernExtension
How can I have a property that holds a List<> of my IUIConcern<T> without knowing T other than knowing it will be derived from IUIConcernExtension?
Again, I realize this doesn't compile and is not correct, just looking to see how I can hold a list of generic items that may have many different type of IUIConcern<> elements.
Thank you!
You need to have a base interface, for instance:
public interface IUIConcern
{
string Name { get; }
}
public interface IUIConcern<out T> : IUIConcern where T : IUIConcernExtension
{
Func<T> Extern();
}
How you would define Concerns and Register would depend on how you treat T. Alternatively if you only deal with instances where you know T, you could use a Dictionary<Type, List<IUIConcern>> to hold anything, or potentially drop the base interface and just store using object depending on what you need in your controller code.
The problem is not located at the interface, but the problem is because of your generic implementation using static methods and properties.
The answer from Guvante was correct when saying that you need to define the IUIConcernExtension, but that is of course very logical, so im assuming you have just omitted that part since it does not matter for the issue you are facing.
The problem in the code is that you have created a class that has static methods and procedures, with the generic definition not laying at class level, but at methods level, because of this, the property that has and the Method cannot assume you are always with the same type!!
Lets say you call call :
Register<string>("something", UIConcern<string>)
but before that you have already called:
Register<Type>("something", UIConcern<Type>)
How could the compiler allows you to that?! So the answer is to define the generic type at class level, with this all properties and methods will be of same .
Also you need to use a private member for your list, since you doing everything static, the correct code should be:
interface IUIConcernExtension
{
string Name { get; }
}
public interface IUIConcern<out T> where T : IUIConcernExtension
{
Func<T> Extend();
}
public class UIConcern<T> where T : IUIConcernExtension
{
private static List<IUIConcern<T>> _Concerns = new List<IUIConcern<T>>();
public static void Register(string concernName, IUIConcern<T> uiConcern)
{
Concerns.Add(uiConcern);
}
public static List<IUIConcern<T>> Concerns
{
get { return _Concerns; }
set { _Concerns = value; }
}
}
I was wondering if anyone could tell me if this kind of behaviour is possible in C# 4.0
I have an object hierarchy I'd like to keep strongly typed. Something like this
class ItemBase {}
class ItemType<T> where T : ItemBase
{
T Base { get; set; }
}
class EquipmentBase : ItemBase {}
class EquipmentType : ItemType<EquipmentBase> {}
What I want to be able to do to have something like this
ItemType item = new EquipmentType();
And I want item.Base to return type ItemBase. Basically I want to know if it's smart enough to strongly typed generic to a base class without the strong typing. Benefit of this being I can simply cast an ItemType back to an EquipmentType and get all the strongly typedness again.
I may be thinking about this all wrong...
You're talking about covariance which would allow you to do:
ItemType<object> item = new EquipmentType();
You couldn't do this in C# 4 because of the following reasons:
Generic covariance only works on interfaces, arrays, and delegate types, not base classes
Your ItemType class uses T as an in/out type parameter meaning it receives a T and also returns a T.
Number 2 is the main issue because if it were allowed, then the following code would have to be compilable, yet fail at runtime.
// this will not work
ItemType<object> item = new EquipmentType();
item.Base = new Object(); // this seems ok but clearly isn't allowed
Covariance and Contravariance FAQ
No, because ItemType as far as the compiler is concerned is a separate type from ItemType<EquipmentBase> or ItemType<Foo>. All three are treated as unique types and they cannot represent one another.
In your class declarations, you declared it as ItemType<T> and so ItemType would be an undefined type which would not compile.
At best, you could use an ItemType<EquipmentBase> object to represent EquipmentType or any other class derived from ItemType<EquipmentBase> but not ItemType<PersonType>.
I don't think that the new features of C# 4.0 will help you out there. However, there is a way around this which already works since generics were introduced: you create an abstract base class with the same name as the generic class and put all members which you want and which don't need to accept or return an argument of the generic type, like so:
class ItemBase {
}
abstract class ItemType {
public ItemBase Base {
get { return GetItemBase(); }
set { SetItemBase(value); }
}
protected abstract void SetItemBase(ItemBase value);
protected abstract ItemBase GetItemBase();
}
class ItemType<T> : ItemType where T : ItemBase {
protected override sealed void SetItemBase(ItemBase value) {
Base = (T) value;
}
protected override sealed ItemBase GetItemBase() {
return Base;
}
public new T Base { get; set; }
}