I want to have a generic class which could call a method based on its generic type which is defined by a derived class. For that I implemented a base interface and a generic interface which has the base interface as generic and also derives from the base interface.
In the generic interface I want a method based on the type T of the base interface.
After that I wanted to implement a class based on the generic interface which should be able to call the generic method. This is the example code:
public interface BaseInterface
{ }
public interface GenericInterface<T> : BaseInterface where T : BaseInterface
{
void Foo(T t);
}
public class C<T> : GenericInterface<T> where T : BaseInterface
{
public C()
{
// None of these works
Foo(this);
Foo((T)this);
Foo((BaseInterface)this);
}
public void Foo(T t) { }
}
Is there a way to achieve my desired behavior here?
The error message here is:
cannot convert from 'C<T>' to 'T'
which in my eyes should be possible because C derives from BaseInterface which is T
While both C<T> and T need to derive from BaseInterface, that does not mean that then need to be the same. I might for example declare another type B : BaseInterface, and C<B>. So we would get the method Foo(B t) , it would obviously not be possible to call the method with this as the parameter, since C<B> is not B.
If you just need a method that needs a BaseInterface parameter, just declare it as Foo(BaseInterface t) instead. That way you could call it with this without any problem.
It looks like you're looking for something like the Curiously Recurring Template Pattern for C#. In a simplified form it looks like this:
class Base<T>
{
public void Foo(T t) { }
}
class C : Base<C>
{
C()
{
Foo(this);
}
}
In your case T is a type that derives from BaseInterface. Although C<T> also derives from BaseInterface it doesn't mean that you can bind a C<T> to T t. It's like trying to bind a string to a List, just because both implement IEnumerable. They are still different types.
For your full example it could look like this
public interface BaseInterface
{ }
public interface GenericInterface<T> : BaseInterface where T : BaseInterface
{
void Foo(T t);
}
public class C<T> : GenericInterface<C<T>> where T : BaseInterface
{
public C()
{
Foo(this);
}
public void Foo(C<T> t) { }
}
Here's what you need for the Curiously Recurring Template in C#.
public interface BaseInterface { }
public interface GenericInterface<T> : BaseInterface where T : GenericInterface<T>
{
void Foo(T t);
}
public abstract class C<T> : GenericInterface<T> where T : C<T>
{
public abstract void Foo(T t);
}
Now you can go ahead and implement a real class:
public class D : C<D>
{
public D()
{
Foo(this);
Foo((D)this);
}
public override void Foo(D t) { }
}
That works fine.
However, calling Foo((BaseInterface)this); will never work in this code. It just doesn't make sense.
I Tried this, maybe can help you
public class C<T> : GenericInterface<T> where T : BaseInterface
{
public C()
{
T t = default(T);
BaseInterface bi;
bi = t; // here can cast , bacuse T : BaseInterface , not BaseInterface : T
t = bi;//here cast error ,
}
public void Foo(T t) { }
}
It's same like this case:
public class B { }
public class A : B
{
public void CastTest()
{
A a = null;
B b = null;
b = a;
a = b;//here error
}
}
Related
Suppose a class defined as below,
public class MyGeneric<T> where T : MyGeneric<T>
{
}
Can we create an object of this class? If not, why does this exist?
I'm asking this of my curiosity and don't have an in depth knowledge in C#.
It's useful when you have a class hierarchy, and you want to be able to write methods in the base class which return instances of the derived class (such as this):
public abstract class Base<T> where T : Base<T>
{
public T WithFoo(int foo)
{
// ...
return (T)this;
}
}
public class Derived : Base<Derived>
{
// ...
}
Derived d = new Derived().WithFoo(3);
Of course, this doesn't stop someone from writing:
public class Other : Base<Derived> { }
... and the only way to get around this is with a runtime check, which can be ugly:
public Base()
{
Trace.Assert(typeof(T) == this.GetType());
}
Some other languages have specific keywords to cover this case.
You can do it by inheriting from MyGeneric:
public class MyGeneric<T> where T : MyGeneric<T>
{
}
class MyGenericChild : MyGeneric<MyGenericChild>
{
}
var myGenericChild = new MyGenericChild();
var myGeneric = new MyGeneric<MyGenericChild>();
This is helpful when there is need to create type-specific members in the base class, specific to the actual descendant.
public class MyGeneric<T> where T : MyGeneric<T>
{
public void Do(T t)
{
...
}
}
class MyGenericChild : MyGeneric<MyGenericChild>
{
// Do for MyGenericChild will accept only MyGenericChild and it's descendants
}
I have a generic interface (MyInterface<T>), which is implemented by the class ChildA in the example below:
public interface MyInterface<T>
{
MyObj<T> GetObj(); // Irrelevant
}
class ChildA : MyInterface<ChildA>
{
// Irrelevant:
MyObj<ChildA> GetObj() {
return new MyObj<ChildA>();
}
}
This works, but I need to make sure that <T> always has the type of the implementing class, so in this case T should always be of type ChildA, because it is implemented by ChildA.
Another correct implementation could be this, for example:
class ChildB : MyInterface<ChildB> { ... }
But currently, this incorrect implementation is also possible, while it should not be:
class ChildA : MyInterface<ChildB> { ... }
Is there a way to enforce this?
You cannot enforce a generic type argument to be constrained to the implementing type.
The available type constraints are the following:
where T : struct
where T : class
where T : new()
where T : <base class name>
where T : <interface name>
where T : U
There is nothing like where T : self in C#. Actually, it wouldn't even make sense, because such a thing cannot be meaningfully enforced. Besides, it wouldn't fit at all into the covariance/contravariance concepts and would be weird to inherit from, in general.
The closest thing you can do is this:
public interface IMyInterface<T> where T : IMyInterface<T>
{
MyObj<T> GetObj();
}
Why it wouldn't make sense
Let's say you could do this:
public interface IMyInterface<T> where T : self // this syntax does not exist in C#
{
MyObj<T> GetObj();
}
Now all implementing types would have to use themselves as the type argument. But you could still do this:
public class ChildC<T> : IMyInterface<T> where T : self
{
/* ... */
}
Which would go around your restriction.
Is there a way to enforce this?
Well, not with generic constraints. You can do that with reflection though i'd vote against it :
public abstract class BaseChild<T> : MyInterface<T>
{
protected BaseChild()
{
if (typeof(T) != this.GetType())
{
throw new InvalidOperationException(string.Format(
"Type {0} is not supported as valid type parameter for type {1}",
typeof(T).Name, this.GetType().Name));
}
}
}
Example :
class ChildA : BaseChild<int> { }
// Bang! throws
var instance = new ChildA();
.
class ChildB : BaseChild<ChildB> { }
// Ok here
var instance = new ChildB();
You cannot do this but you can create your own control comparing the generic type of the interface and the type of your class. See the example:
class ChildA : MyInterface<ChildB>
{
public ChildA()
{
this.ValidateGenericType();
}
public MyObj<ChildB> GetObj()
{
return new MyObj<ChildB>();
}
protected void ValidateGenericType()
{
//throws an Exception because ChildB is different of ChilA
if (this.GetType().Name != this.GetType().GetInterfaces()[0].GetGenericArguments()[0].Name)
{
throw new Exception("The generic type must be of type ChildA.");
}
}
}
It seems that you should use extension methods instead of enforcing some interface for this purpose
public interface ISomeInterface {}
public class Child: ISomeInterface {}
public class OtherChild : ISomeInterface { }
public static class MyInterfaceExtensions
{
public static MyObj<T> GetMyObj<T>(this T child) where T : ISomeInterface
{
return new MyObj<T>();
}
}
public static class Test
{
public static void RunTest()
{
var child = new Child();
var otherChild = new OtherChild();
MyObj<Child> myObj = child.GetMyObj();
MyObj<OtherChild> myOtherObj = otherChild.GetMyObj();
}
}
I'm not sure if this is possible at all, looking for some clarification.
I have a class structure like this:
public class FooBase
{
//Some base class
}
public class BarBase
{
//Some base class
}
public class Foo : FooBase
{
//Implementation
}
public class Bar : BarBase
{
//Implementation
}
public abstract class FooBarHolderAbstract<T, V> where T: FooBase where V: BarBase
{
}
public class MyFooBarHolderImpl : FooBarHolderAbstract<Foo, Bar>
{
}
public class FooBarTest
{
public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<FooBase, BarBase>
{
//Do something tith the obj
}
public void RunTest()
{
//This doesn't work, compiler says MyFooBarHolder is not convertible to FooBarHolderAbstract<FooBase, BarBase>
DoSomethingWithFooBar<MyFooBarHolderImpl>();
}
}
In the FooBarTest class, I'd like to create a method which accepts a generic parameter, which inherits from the abstract class having two generic parameters. The class MyFooBarHolderImpl extends the abstract base class and specifies its generic parameters with types which are inheriting from the abstract class' generic parameter types.
When I try to call this method (DoSomethingWithFooBar()) the compiler tells me that the type MyFooBarHolderImpl must be convertible to FooBarHolderAbstract
Is this something which cannot be done at all, or am I missing a concept/syntax?
Thanks in advance!
Well, it can't be done directly - a FooBarHolderAbstract<Foo, Bar> isn't a FooBarHolderAbstract<FooBase, BarBase>. It's not clear whether or not you could logically have that, because we don't know what's in the abstract class.
You're basically looking for generic covariance, but that isn't supported on classes anyway - so you may want to introduce an interface:
public interface IFooBarHolder<out T, out V>
where T: FooBase
where V: BarBase
{
// Define what you need in here
}
public abstract class FooBarHolderAbstract<T, V> : IFooBarHolder<T, V>
where T : FooBase
where V : BarBase
{
}
At that point, you can change FooBarTest to:
public void DoSomethingWithFooBar<T>() where T : IFooBarHolder<FooBase, BarBase>
{
//Do something with the obj
}
... because an IFooBarHolder<Foo, Bar> is an IFooBarHolder<FooBase, BarBase>.
However, this only works if you can define all your operations for the interface which use T and V in "out" positions, e.g. return types from methods. If you ever need them in "input" positions, e.g. as method parameters, you're stuck - because a method expecting a Foo can't handle any other kind of FooBase.
It doesn't clear, what are you going to do in DoSomethingWithFooBar, since you don't pass any parameter, but here are another options:
public class FooBarTest
{
public void DoSomethingWithFooBar<TFooBase, TBarBase>(FooBarHolderAbstract<TFooBase, TBarBase> obj)
where TFooBase : FooBase
where TBarBase : BarBase
{
//Do something tith the obj
}
public void RunTest()
{
DoSomethingWithFooBar<Foo, Bar>(new MyFooBarHolderImpl());
}
}
or
public class FooBarTest
{
public void DoSomethingWithFooBar<TFooBase, TBarBase, THolder>()
where TFooBase : FooBase
where TBarBase : BarBase
where THolder : FooBarHolderAbstract<TFooBase, TBarBase>
{
//Do something tith the obj
}
public void RunTest()
{
DoSomethingWithFooBar<Foo, Bar, MyFooBarHolderImpl>();
}
}
You have to write your FooBarTest as below. You have to define T for DoSomethingWithFooBar<T> as FooBarHolderAbstract<Foo, Bar>
public class FooBarTest
{
public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<Foo, Bar>
{
//Do something tith the obj
}
public void RunTest()
{
DoSomethingWithFooBar<MyFooBarHolderImpl>();
}
}
I have below class structure:
public class FirstContextController : AFirstContextController
public abstract class AFirstContextController : ABaseController<AFirstContextView>
public abstract class ABaseController<TView> where TView : ABaseView
public abstract class AFirstContextView : ABaseContextView
public abstract class ABaseContextView : ABaseView
public abstract class ABaseView : UserControl
Now I create an instance of my controller:
AFirstContextController firstContextController = new FirstContextController();
and need to return it from the method:
public static ABaseController<ABaseContextView> GetContextController( ... )
{
return firstContextController;
}
But then I get an error:
Cannot implicitly convert type 'AFirstContextController' to 'ABaseController'
So I tryied many casting (for example):
return (ABaseController<AFirstContextView>)firstContextController;
return (ABaseController<ABaseContextView>)( (ABaseController<AFirstContextView>)firstContextController );
But still get similar errors according to conversion.
So what conversion should I apply to return it ?
You need an interface derived from ABaseController<ABaseContextView> to make it work.
This has to do with variance and covariance. Reed more about it on MSDN: Covariance and Contravariance in Generics.
You will have to mark the ABaseContextView with out in your interface definition, so the signature should be something like IBaseController<out ABaseContextView>.
Example:
public abstract class ABaseController<TView> : IBaseController<TView> where TView : ABaseView
{
public void SomeMethod() { }
}
And the interface:
public interface IBaseController<out TView> where TView : ABaseView
{
void SomeMethod();
}
Then your current method should read:
public static IBaseController<ABaseContextView> GetContextController( ... )
{
return firstContextController;
}
My project is structured the following way:
// Abstract class
public abstract class Job
{
public abstract JobResult Run();
}
public abstract class JobResult { }
// Concrete implementer
public class Job1 : Job
{
public override Job1Result Run() { }
}
public class Job1Result : JobResult { }
Each concrete job inherits from Job and implements the method Run which returns a concrete class of JobResult.
However when I do this I get the compiler error:
Job1.Run()': return type must be JobResult to match overridden member
Job.Run()
Is it really not possible to return an inheriting object of the return type when overriding an abstract method?
This is the whole concept of inheritance. Returning parent classes is considered a feature here. Nothing stops you however from returning a Job1Result in Job1
public JobResult Run()
{
return new Job1Result();
}
Then the caller of Job1.Run() will have to know the correct return type and cast it to access Job1Result methods which are specific to that class
You could make Job generic:
public abstract class Job<TResult> where TResult : JobResult
{
public abstract TResult Run();
}
public class Job1 : Job<Job1Result>
{
public override Job1Result Run()
{
//
}
}
Here is an example, I hope it can help you.
public interface IEvent
{
Type GetEventType();
}
public abstract class AEvent<A>: IEvent where A: struct
{
public Type GetEventType()
{
return typeof (A); // return sub struct type
}
}