This is an extension to my previous question: Type safety through inheritance
I created a new question instead of updating my old as this one dives deeper into this topic.
My original purpose was to declare a method that returns an object of the implementing classes type. One such method might look like GetSimpleClone() in the following:
I have a base interface IEntity that declares the method GetSimpleClone() and is implemented by several other interfaces, for example IPerson.
public interface IEntity<T> : where T : IEntity<T>
{
T GetSimpleClone();
}
public interface IPerson : IEntity<IPerson>
{
}
The interface IAddress also implements IEntity. However another interface IVenue inherits from IAddress. As I described in the beginning, I want the GetSimpleClone() method in IAddress to return an object of type IAddress while the same method in IVenue should return an object of type IVenue. Therefore the declaration of IAddress differs from IPerson as it has to declare a generic type itself:
public interface IAddress<T> : IEntity<T> where T : IAddress<T>
{
}
public interface IVenue : IAddress<IVenue>
{
}
Now the problem is that IPersonhas a reference to IAddress and understandably the compiler forces me to define the generic type of IAddress.
public interface IPerson : IEntity<IPerson>
{
IAddress<"Compiler: Define Type!!"> Address { get; set; }
}
I really can't see a solution to this problem and would appreciate any help from you, even if it is just to say that there is simply no solution. :)
Thanks in advance...
To accomplish that, you will need to introduce yet another generic:
public interface IPerson<T> : IEntity<IPerson<T>>
where T : IAddress<T>
{
IAddress<T> Address { get; set; }
}
The better solution I could think of is just to put aside the safety thing and create a good base IAddress interface with a common methods, like getAddressString, and use it for all types of addresses you may want to have.
Related
Been struggling with this for a bit so wanted to see if someone here might know the solution. I have a set of interfaces (and an implementation):
public interface IInputValue
{
}
public interface IInputValue<T> : IInputValue where T : struct
{
T Value { get; set; }
}
public class ButtonInputValue : IInputValue<bool>
{
private bool m_Value;
public bool Value
{
get => m_Value;
set => m_Value = value;
}
}
And then I have a scriptable object class that inherits and uses implementations of IInputValue<T>.
public abstract class InputTrigger : ScriptableObject
{
}
public abstract class InputTrigger<T> : InputTrigger where T : IInputValue
{
public abstract T InputValue { get; }
}
T for example, could be ButtonInputValue. I want to serialize this scriptable object in another class (as InputTrigger) and simply be able to call .InputValue on it to get the correct derived type of IInputValue or just get the primitive value directly through IInputValue<T>.Value. What's the best way to go about doing this? Any help is much appreciated.
I think you are trying to use interfaces in the wrong way.
The purpose of an interface is to abstract common functionality on potentially completely different objects and not caring about the base class that implements the interface.
For instance:
You can have a car object and a electric car objects and they can both accelerate and brake. They do so in different ways but all you need to know is that they can accelerate and brake using the pedals (the interface), without you going to learn to drive a car once again.
To answer your question, I think you can use the interface as a type and call the method on the object, and in case you need to verify it is a certain type that implements that interface you can cast to it.
IInputValue<bool> myInputValue;
(ButtonInputValue) myInputValue; // This will be treated as ButtonInputValue because the class implements the IInputValue interface.
I am getting an object of type Company<IDesignation>. Now I want to cast it to ICompany<Manager>. Run time I know that IDesignation is nothing but "Manager" type.
Is this what you are looking for?
Company comp = new Company();
Manager mgner = new Manager(comp.getManager());
IDesignation manager = mgner;
ICompany company = (ICompany)manager;
Assuming Company is:
public class Company: ICompany, IDesignation //or something?
Using either Generic Type Casting (what u are trying to do) or simply Casting an Interface or object depends on whether you will perform this task explicitly or implicitly (maybe class has pre-defined function to cast it) and as your comment has pointed out... maybe by user or runtime matters or whether or not and/or how you need to instantiate your object so I would really need to see the class implementation in order to be able to provide something that uses type casting in the way you want to perform it.
What you need is Contravariance, i.e. your IEntityDelta generic type parameter needs to be made contravariant.
The only way to do that and for this to work is to have:
public interface IEntityDelta<in T> : IEntityDelta where T : IEntity
Note the in T in the definition.
Check out the in (Generic Modifier) (C# Reference)
Or this Understanding Covariant and Contravariant interfaces in C#
If you're not the creator of that interface and if the IEntityDelta<> is defined w/o the in modifier you're out of luck.
And just to mention that adding in/out modifiers is easier said than done. For that to compile your methods, properties etc. need to satisfy
the conditions of contravariance (or covariance in case of 'out') on that generic type (T) parameter.
And this what your classes, interfaces look like based on your info (which was terrible btw. next time you need to dedicate a bit more time
in providing minimal but complete code that makes sense):
public interface IEntityDelta<in T> : IEntityDelta
where T : IEntity
{
void MakeDelta(T entity); // this is allowed
//T Entity { get; set; } // this won't work
}
public class EntityDelta<T> : IEntityDelta<T>
where T : class, IEntity
{
public T Entity { get; set; }
public EntityDelta(T entity) => Entity = entity;
public void MakeDelta(T entity) { }
}
public interface IEntityDelta { }
public abstract class Entity : IEntity { }
public class Order : Entity { }
public interface IEntity { }
...and usage:
var order = new Order();
EntityDelta<IEntity> orderDelta = new EntityDelta<IEntity>(order);
IEntityDelta<IEntity> idelta = orderDelta;
IEntityDelta<Order> iOrderDelta = orderDelta;
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 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; }
}