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>();
}
}
Related
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
}
}
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've got an issue with generics. I've those classes :
abstract class BaseTestClass<T> : where T : class, new()
{
//base test class implementation
public abstract void Run(BaseDataClass<T> data);
}
class BaseDataClass<T> : where T : class, new()
{
//base data class implementation
}
class DataA : BaseDataClass<SettingsA>
{
//some stuff
}
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
}
//Doesn't Work!
public override void Run(DataA data)
{
}
}
My question if why can't I use the inherited class in the abstract method ?
[EDIT]
The error at compilation is:
TestA does not implement inherited abstract member Run(BaseDataClass)
You can, but the BaseTestClass<SettingsA> base class simply does NOT have a method to override of the signature Run(DataA), but only one of the signature Run(BaseDataClass<DataA>).
The generic inheritance also means that the generic T type is the same.
You can implement this with an additional generic argument, Type-Safe and without cast:
internal abstract class BaseTestClass<T, Y>
where T : class, new()
where Y : BaseDataClass<T>
{
private T m_data;
//base test class implementation
public abstract void Run(Y data);
}
public class BaseDataClass<T> where T : class, new()
{
}
internal class TestA : BaseTestClass<SettingsA, DataA>
{
public override void Run(DataA data)
{
throw new NotImplementedException();
}
}
class DataA : BaseDataClass<SettingsA>
{
}
class SettingsA
{
}
This is type-safe because the constraint is
where Y : BaseDataClass<T>
If you don't need T directly in you base class, you can only use one generic parameter and remove T
Your second method does not compile because there is no method to be overriden by it, removing the override modificator will make your code compile.
If you want to have a method which will run only when the parameter is of type DataA, but still execute the interface method implementation, you can do this way:
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
}
public void Run(DataA data)
{
//dp some stuff
Run((BaseDataClass<SettingsA>)data);
}
}
But note that this is not bullet proof, you could miss boxed calls, the better way is do this way:
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
var myDataA = data as DataA;
if (myDataA != null)
{
//your parameter is a DataA;
}
}
}
It does not work because you cannot override one method with two methods. Take the override off of one of the methods in TestA, and it will all work. There's no point in overriding a single method twice, anyhow, within a single class.
Consider the following code:
abstract class Foo<T>
where T : Foo<T>, new()
{
void Test()
{
if(Bar != null)
Bar(this);
}
public event Bar<T> Bar;
}
delegate void Bar<T>(T foo)
where T : Foo<T>, new();
The line Bar(this) results in the following compiler Error:
Argument type Foo<T> is not assignable to parameter type T
T is constrained to Foo<T> as I want derived classes to basically tell the base class their type, so that the type can be used in the event callback in order to save the implementor from having to cast the callback argument to the derived type.
I can see the code doesn't quite work but I'm having a bit of a blockage as to how to do this correctly without ending up with a generic delegate that can be used for any old thing. I'm also not quite sure why the T constraint doesn't create a compiler error considering it seems to be recursive.
EDIT
I need to clarify this I think! Here's a new example which, I hope will be much clearer. Note below that the OnDuckReady event handler below generates a compiler error.
How do I get the event to pass in the correct type?
abstract class Animal<T>
where T : Animal<T>, new()
{
void Test()
{
if(AnimalReady != null)
AnimalReady(this);
}
public event AnimalHandler<T> AnimalReady;
}
delegate void AnimalHandler<T>(Animal<T> animal)
where T : Animal<T>, new();
class Duck : Animal<Duck>
{
public void FlyAway()
{
}
}
class Test
{
void Main()
{
Duck duck = new Duck();
duck.AnimalReady += OnDuckReady; // COMPILER ERROR
}
void OnDuckReady(Duck duck)
{
duck.FlyAway();
}
}
You can cast 'this' to T:
Bar((T)this);
This however will fail if you have the following:
public class MyFoo : Foo<MyFoo> { }
public class MyOtherFoo : Foo<MyFoo> { }
Because 'MyOtherFoo' is not an instance of 'MyFoo'. Take a look at this post by Eric Lippert, one of the designers of C#.
The code would be clearer if you didn't use "Bar" for two purposes. That having been said, I think what's needed is to use a generic with two parameters (e.g. T and U) such that T derives from U, and U derives from Foo. Alternatively, it's possible to do some nice things with interfaces. A useful pattern is to define:
interface ISelf<out T> {T Self<T> {get;}}
and then, for various interfaces that one might want to combine in an object:
interface IThis<out T> : IThis, ISelf<T> {}
interface IThat<out T> : IThat, ISelf<T> {}
interface ITheOtherThing<out T> : ITheOtherThing, ISelf<T> {}
If classes that implement IThis, IThat, and ITheOtherThing also implement ISelf<theirOwnTypes>, one can then have a routine whose parameter (e.g. "foo") has to implement both IThis and IThat accept the parameter as type IThis. Parameter "foo" will be of type IThis (which in turn implements IThis) while Foo.Self will be of type IThat. Note that if things are implemented this way, one may freely typecast variables to any desired combination of interfaces. For example, in the above example, if the object passed as "foo" was a type which implemented IThis, IThat, ITheOtherThing, and ISelf<itsOwnType> it could be typecast to ITheOtherThing>, or IThis, or any other desired combination and arrangement of those interfaces.
Really a pretty versatile trick.
Edit/Addendum
Here's a somewhat more complete example.
namespace ISelfTester
{
interface ISelf<out T> {T Self {get;} }
interface IThis { void doThis(); }
interface IThat { void doThat(); }
interface IOther { void doOther(); }
interface IThis<out T> : IThis, ISelf<T> {}
interface IThat<out T> : IThat, ISelf<T> {}
interface IOther<out T> : IOther, ISelf<T> {}
class ThisOrThat : IThis<ThisOrThat>, IThat<ThisOrThat>
{
public ThisOrThat Self { get { return this; } }
public void doThis() { Console.WriteLine("{0}.doThis", this.GetType()); }
public void doThat() { Console.WriteLine("{0}.doThat", this.GetType()); }
}
class ThisOrOther : IThis<ThisOrOther>, IOther<ThisOrOther>
{
public ThisOrOther Self { get { return this; } }
public void doThis() { Console.WriteLine("{0}.doThis", this.GetType()); }
public void doOther() { Console.WriteLine("{0}.doOther", this.GetType()); }
}
class ThatOrOther : IThat<ThatOrOther>, IOther<ThatOrOther>
{
public ThatOrOther Self { get { return this; } }
public void doThat() { Console.WriteLine("{0}.doThat", this.GetType()); }
public void doOther() { Console.WriteLine("{0}.doOther", this.GetType()); }
}
class ThisThatOrOther : IThis<ThisThatOrOther>,IThat<ThisThatOrOther>, IOther<ThisThatOrOther>
{
public ThisThatOrOther Self { get { return this; } }
public void doThis() { Console.WriteLine("{0}.doThis", this.GetType()); }
public void doThat() { Console.WriteLine("{0}.doThat", this.GetType()); }
public void doOther() { Console.WriteLine("{0}.doOther", this.GetType()); }
}
static class ISelfTest
{
static void TestThisOrThat(IThis<IThat> param)
{
param.doThis();
param.Self.doThat();
}
static void TestThisOrOther(IThis<IOther> param)
{
param.doThis();
param.Self.doOther();
}
static void TestThatOrOther(IThat<IOther> param)
{
param.doThat();
param.Self.doOther();
}
public static void test()
{
IThis<IThat> ThisOrThat1 = new ThisOrThat();
IThat<IThis> ThisOrThat2 = new ThisOrThat();
IThis<IOther> ThisOrOther1 = new ThisOrOther();
IOther<IThat> OtherOrThat1 = new ThatOrOther();
IThis<IThat<IOther>> ThisThatOrOther1 = new ThisThatOrOther();
IOther<IThat<IThis>> ThisThatOrOther2a = new ThisThatOrOther();
var ThisThatOrOther2b = (IOther<IThis<IThat>>)ThisThatOrOther1;
TestThisOrThat(ThisOrThat1);
TestThisOrThat((IThis<IThat>)ThisOrThat2);
TestThisOrThat((IThis<IThat>)ThisThatOrOther1);
TestThisOrOther(ThisOrOther1);
TestThisOrOther((IThis<IOther>)ThisThatOrOther1);
TestThatOrOther((IThat<IOther>)OtherOrThat1);
TestThatOrOther((IThat<IOther>)ThisThatOrOther1);
}
}
}
The thing to note is that some classes implement different combinations of IThis, IThat, and IOther, and some methods require different combinations. The four non-static classes given above are all unrelated, as are the interfaces IThis, IThat, and IOther. Nonetheless, it is possible for method parameters to require any combination of the interfaces provided that implementing classes follow the indicated pattern. Storage locations of a "combined" interface type may only be passed to parameters which specify the included interfaces in the same order. An instance of any type which properly implements the pattern, however, may be typecast to any "combined" interface type using any subset of its interfaces in any order (with or without duplicates). When used with instances of classes that properly implement the pattern, the typecasts will always succeed at run-time (they could fail with rogue implementations).
delegate void Bar<T>(Foo<T> foo) where T : Foo<T>, new();
It works great. I tested it.
here is the test code
public abstract class Foo<T> where T :Foo<T> {
public event Bar<T> Bar;
public void Test ()
{
if (Bar != null)
{
Bar (this);
}
}
}
public class FooWorld : Foo<FooWorld> {
}
public delegate void Bar<T>(Foo<T> foo) where T : Foo<T>;
class MainClass
{
public static void Main (string[] args)
{
FooWorld fw = new FooWorld ();
fw.Bar += delegate(Foo<FooWorld> foo) {
Console.WriteLine ("Bar response to {0}", foo);
};
fw.Test ();
}
}
Let's say I have some basic interface which is generics-driven:
public interface Inteface<T> {
void Foo(T t);
}
Now I have some concrete implementation of this interface which is also generic:
public class InterfaceImpl<T> {
public void Foo(T t) {
// Whatever
}
}
This looks OK, but now let's say I have other class:
public class Ololo {
public void BadFunction<TShouldModelInterface>(TShouldModelInterface shouldModelInterface) {
// Whatever
}
}
And let's say I want to perform a check if TShouldModelInterface actually implements any of the possible Interface<T>.
If the interface wasn't generic, I would simply write something like where TShouldModelInterface : Interface.
But is there any way to solve this problem if the interface is a declared as Interface<T>?
public class Ololo {
public void BadFunction<TShouldModelInterface, T>(TShouldModelInterface shouldModelInterface)
where TShouldModelInterface : Interface<T>
{
// Whatever
}
}