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; }
}
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 relatively newbie to C# programming. I want to create Abstract Base Class that contains a few of abstract, and virtual methods.
By the following two examples, what are their differences of usage and which is more commonly used?
Example-1, use Type keyword.
public abstract class DecoratorBase<Type> : ValidatableBindableBase
{
public virtual void SetFields(Type T) { }
public virtual void SetFieldsBack(ref Type T) { }
}
Example-2, use Object keyword.
public abstract class DecoratorBase<Object> : ValidatableBindableBase
{
public virtual void SetFields(Object T) { }
public virtual void SetFieldsBack(ref Object T) { }
}
In my case, Type or Object will represent my business model POCO class.
Sorry, if this question sound so naive to you. Thanks.
Please, don't do that!
It looks like you're a little confused about generics. When you define a generic abstract type (using < and > after the name), you're telling the compiler "I will give you some type, but I don't know which type just now. Use the name I'm giving you as a placeholder for the type later." The convention is to use the upper case T.
For example, the following defines a generic abstract class.
public abstract class SomeClass<T> {}
Later, when we create a derived class, we create it with a type:
public class ConcreteClass : SomeClass<int> {}
If we had methods declared in our abstract class that used the type T, our new ConcreteClass would replace references to T with int. So in your case, you should do:
public abstract class DecoratorBase<T> : ValidatableBindableBase
{
public virtual void SetFields(T param) { }
public virtual void SetFieldsBack(ref T param) { }
}
You can see here, T represents the unknown type as T, instead of naming the type Type and the parameter T. What you were doing is known as 'hiding', that is, When you use Type or Object in the way you were doing, it is assigning a new meaning to those words. You should absolutely avoid hiding in this way.
Now if you create a concrete class, say:
public class Decorator : DecoratorBase<Control>
{
public override SetFields(Control param) {}
}
You have type safety: the parameter now has to be a Control, at least for this concrete implementation. You can define other implementations with different types, and inherit the same base methods.
See this question for a simple understanding of how to use generics.
I am trying to design an interface, so that it has a generic type of id and a generic method that returns the type of the class that implements this interface. For example:
public interface IEntity <IDType, MethodReturnType>
{
IDType ID {get; set;}
MethodReturnType Get();
}
public class Model : IEntity<int, Model>
{
int ID {get; set; }
Model Get() { // do something }
}
My question is, it seems silly to put in Model as the second type parameter of IEntity, because I am already in a Model's class, it should be some intelligence way to figure out what type it is (although using generic type requires it to be determined before compile time).
Is it any other solution that can help me to get rid of the Model type while retain the Get method definition in the interface?
In this context, there are two typical ways to go about designing your classes and interfaces. I'll stray slightly from your exact example to try to make the answer more general.
Which option to choose really depends on how you want your classes and interfaces to be used.
Option 1
Make your interface generic, so that the interface members have knowledge of the exact type.
public interface IEntity<TDescription>
{
TDescription Get();
}
public class MyModel : IEntity<MyDescription>
{
MyDescription Get() { ... }
}
public class MyDescription { ... }
This means that when you use your interface IEntity<TDescription> you need to know TDescription at the time of use. The benefit is that you get more compile-time type checking.
Option 2
Do not make your interface generic and instead have your interface members use interfaces as well.
public interface IEntity
{
IDescription Get();
}
public interface IDescription { ... }
public class MyModel : IEntity
{
MyDescription Get() { ... }
IDescription IEntity.Get() { return this.Get(); }
}
public class MyDescription : IDescription { ... }
This is more flexible, but it also means less compile-time type checking.
You can determine the inherited class type with this.GetType() but that will not allow you to create generic functions/parameters/etc as you are doing.
So to your answer, no, you can't unless you will not use that type in any way (you can still get the base type of the class and use it but cannot set it as return type/param type/etc).
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.
It is quite puzzling to find out that Generics Constraint Can't Be Casted to Its Derived Type.
Let's say I have the following code:
public abstract class BaseClass
{
public int Version
{ get { return 1; } }
public string FixString { get; set; }
public BaseClass()
{
FixString = "hello";
}
public virtual int GetBaseVersion()
{
return Version;
}
}
public class DeriveClass: BaseClass
{
public new int Version
{ get { return 2; } }
}
And guess what, this method will return a compilation error:
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)baseClass;
}
I would have to cast the baseClass to object first before I can cast it to DerivedClass, i.e.,
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)((object)baseClass);
}
Seems to me pretty ugly. Why this is so?
First, you shouldn't be casting a base type variable to a derived type. It's not supposed to work, only the other way around.
Second, why it works via object, is because you remove the compile-time type checks. The compiler can check that a BaseType cannot be cast to DerivedType. But when a variable is object, the compiler leaves it assuming you know what you're doing. Even if it will compile, the code will then crash during execution.
The answer is simple: the compiler can't know that T in your FreeConversion method can be converted to DeriveClass.
As you already stated, the cheap trick is to first cast to object, then to the type you want to go. Ugly, but it works.
Apart from that, it may be that you are violating Liskov Substitution principle, nothing that will harm any animals but can drive your design towards unmaintainable code.
Third, a nice trick to let your base class expose the derived type is something like this:
public class Base<T> where T : Base<T> {
T IAmDerived;
}
public class Derived : Base<Derived> { }
First of all, in your generic method the type T could be a vale type or reference type. And the reason why it allows you to do via 'Object' is that, you're simply doing boxing-unboxing which works for any type in system.
Secondly.it will be a terrible idea to convert/cast a baseclass object into a derived class. You're violating the mechanics of OOP.
If you really want to return an object of type derived from the base class, here's one way possible - the solution is pretty much similar to what Frank has offered.
//This is how you create a function in BaseClass that returns the collection
//of DerivedTypes when called from an object of type derivedclass, no magic just Generics.
//**The BaseClass**
public class BaseClass<T>
where T : BaseClass<T>
{
public HashSet<T> GetHashSet()
{
HashSet<T> _hSet = new HashSet<T>();
//do some work
//create a HashSet<T> and return;
return _hSet;
}
}
//**The Derived Class**
public class DerivedClass : BaseClass<DerivedClass>
{
//you have the method inherited.
}