I'm getting a compile error when I try to compile this
The type 'WpfApplication2.CommandInstrumentTrade' cannot be used as type parameter 'T' in the generic type or method 'WpfApplication2.GenericWindowBase'. There is no implicit reference conversion from 'WpfApplication2.CommandInstrumentTrade' to 'WpfApplication2.GenericCommandBase'
public interface IBaseClass
{
int ID { get; set; }
}
public class BaseClass : IBaseClass
{
public int ID { get; set; }
}
public class DerivedClass : BaseClass
{
}
public class Command
{
}
public class GenericCommandBase<T> : Command where T : IBaseClass
{
}
public class DerivedGenericCommand : GenericCommandBase<DerivedClass>
{
}
public class GenericWindowBase<T> where T : GenericCommandBase<IBaseClass>
{
}
public class DerivedGenericWindow : GenericWindowBase<DerivedGenericCommand> // this line fails
{
}
The issue is that Generic<Derived> does not satisfy the condition where T : Generic<Base>. Even if Derived derives from Base, Generic<Derived> does not derive from Generic<Base>
There are many questions like that in StackOverflow.
Try reading those:
C# Generics Inheritance
generic inheritance in C#?
Inheritance doesn't compose with generics. You need to create some kind of converter from one to another. Maybe if you present some less abstract code we could help You
Related
This question already has answers here:
Convert List<DerivedClass> to List<BaseClass>
(13 answers)
Closed 5 years ago.
Let's consider that there is an abstract base class and one, or more child classes:
public abstract class BaseInnerClass
{
public int Id { get; set; }
}
public class ConcreteInnerClass : BaseInnerClass
{
public string Name { get; set; }
}
Then, let's assume there is a generic abstract class that has a property of above abstract class type:
public abstract class GeneriAbstractTestClass<T> where T : BaseInnerClass
{
public T InnerClass { get; set; }
}
Then let's make a class that inherits from the class above:
public class ConcreteTestClass : GeneriAbstractTestClass<ConcreteInnerClass>
{
public string ConcreteString { get; set; }
}
So now everything is prepared to ask a question ;) Why it is not possible to do it:
//cannot convert initializer type
GeneriAbstractTestClass<BaseInnerClass> genericClass = new ConcreteTestClass();
while this is allowed:
//ok
BaseInnerClass baseInner = new ConcreteInnerClass();
What's the difference between this two assignments?
This has nothing to do with abstract classes. A simpler example would be
List<BaseInnerClass> base = new List<ConcreteInnerClass>
The fact that type A is derived from type B does not imply that type C<A> is derived from type C<B>. Your example is a little bit more complicated, but it can be explained using the same logic.
Note that you can define another concrete type:
public class EvilConcreteInnerClass : BaseInnerClass
{
}
If what you wanted was possible, then the following would work:
GeneriAbstractTestClass<BaseInnerClass> genericClass = new ConcreteTestClass();
genericClass.InnerClass = new EvilConcreteInnerClass(); // OK, because the compiler sees `T` as `BaseInnerClass`
genericClass variable points to an object whose T generic parameter is ConcreteInnerClass, so assigning EvilConcreteInnerClass to the property would result in a run-time exception.
Actually. You can do this. But you need to specify interface with covariant out T generic, because it is type safe to make those casts.
Example
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
var a = new Generic<Concrete>();
IGeneric<Base> c = new Generic<Base>();
c = a;
}
}
public interface IGeneric<out T> where T: Base
{
T Inner { get; }
}
public class Generic<T> : IGeneric<T>
where T : Base
{
public T Inner { get; set; }
}
public class Concrete : Base
{
}
public class Base
{
}
}
Delegates also not restricted if they specify covariant out generic templates.
It means those casts you want is OK as long as you use readonly generic properties. So, like #Kapol said and provided you example why it is not type safe to allow setters on properties or pass T into function.
Summary
Use ReadOnly interfaces if you want to use those kinds of casts.
When a do this:
public class ball {
ITeste<IItem> Teste{ get; set; }
}
I got the error:
'IItem' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'T' in the generic type or
method
ITeste:
public interface ITeste<T>
where T : IItem, IEquatable<T>, new()
{
//ITeste code
}
IItem:
public interface IItem : IEquatable<IItem>
{
//IItem Code
}
It seems to be a simple question, but I could not find the answer. Any help it would be appreciated.
Remove new() from the constraints for ITeste
ITeste:
public interface ITeste<T>where T : IItem, IEquatable<T>
{
//ITeste code
}
Is it possible to create a generic class<T> which the generic type T will be the base class of it?
i.e:
MyClass<Base1> b1 = new MyClass<Base1>();
MyClass<Base2> b2 = new MyClass<Base2>();
b1.Name="test";
b2.ID=1;
Base Classes:
class Base1
{
protected string Name{ get; set;}
}
class Base2
{
protected int ID{ get; set;}
}
Inherited Class:
class MyClass<T>:T //here is the question is it possible dynamic inheritence
{
}
It's possible to use a constraint on T thus forcing T to be of type baseclass, like this:
public class baseclass
{
// base class code
}
// perfectly valid
public class derived1<T> : baseclass where T : baseclass
{
// derived class code
}
It's impossible to compile the following code, since T is a type parameter, and the compiler must infer it from usage. obviously that can't be done like this.
public class derived2<T> : T
{
// derived class code
}
I've got the following generic abstract class:
public abstract class MyClass<F, T>
where TCurrencyFrom : Book
where TCurrencyTo : Book
{
public int Id { get; set; }
public virtual F First{ get; set; }
public virtual T Second { get; set; }
}
And I got 3 classes which implement this class like:
public class Implementation1 : MyClass<BookType1, BookType2>
{
}
public class Implementation2 : MyClass<BookType2, BookType1>
{
}
Now I got an "EntityTypeConfiguration" for those which looks like:
public class MyClassConfiguration<TMyClass> : EntityTypeConfiguration<TMyClass> where TMyClass: MyClass
{
public MyClassConfiguration()
{
...
}
}
And try to use those like:
public class Implementation1Map : MyClassConfiguration<Implementation1>
{
public Implementation1Map ()
{
...
}
}
But then I get the following error:
Incorrect number of type parameters in reference class MyClass
How can I solve this problem and make sure I have a generic approach on the EntityTypeConfigurations?
Unfortunately this is tricky with .NET generics.
If MyClassConfiguration doesn't actually care about the type arguments, you might want to create a non-generic interface:
public interface IMyClass
{
// Any members of MyClass<,> which don't rely on the type arguments,
// e.g. the Id property
}
Then make MyClass<,> implement IMyClass:
// Type parameters renamed to make the type constraints sensible...
public abstract class MyClass<TCurrencyFrom, TCurrencyTo> : IMyClass
where TCurrencyFrom : Book
where TCurrencyTo : Book
And change the type constraint for MyClassConfiguration:
public class MyClassConfiguration<TMyClass> : EntityTypeConfiguration<TMyClass>
where TMyClass: IMyClass
(Obviously you'll want to give IMyClass a more useful name...)
Alternatively, just make MyClassConfiguration generic in three type parameters:
public class MyClassConfiguration<TMyClass, TCurrencyFrom, TCurrencyTo>
: EntityTypeConfiguration<TMyClass>
where TMyClass: MyClass<TCurrencyFrom, TCurrencyTo>
where TCurrencyFrom : Book
where TCurrencyTo : Book
public class Implementation1Map
: MyClassConfiguration<Implementation1, BookType1, BookType2>
public class Implementation2Map
: MyClassConfiguration<Implementation2, BookType2, BookType1>
It's ugly, but it'll work.
I have this code for example
public class BaseClass
{}
public class DerivedClass1 : BaseClass
{}
public class DerivedClass2 : BaseClass
{ }
public class DerivedClass3 : BaseClass
{ }
public class GenericBaseClass<T> where T : BaseClass
{
public List<T> collection { get; set; }
}
Now I'd like to create a new class which would inherit from GenericBaseClass<T> and have somehow a collection List in this class.
Is this even possible this way ?
Because List<BaseClass> = new List<DerivedCLass3>(); isn't valid.
Or the only way to achieve this is to remove the collection property from the GenericBaseClass and add a collection List directly in the derived class.
I hope I expressed myself understandable as English isn't my first language :-)
public class GenericBaseClass<T> where T : BaseClass
{
public List<T> collection { get; set; }
}
public class GenericDerivedClass1 : GenericBaseClass<DerivedClass1>
{
// Here the collection property will be of type List<DerivedClass1>
}
The reason why your sample code can't compile is due to covariance. .Net can't handle auto typing of a class that is less specific than itself. I believe this is all changing in .Net 4.5 though and what you are trying to do may in fact be supported.
Covariance and contravariance (computer science)