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
}
}
Related
I've been trying to apply SOLID principles more consciously on my current project. Using interfaces to create the abstraction and allowing classes that are handling the dependency injection to provide the concretions has really helped with decoupling some of the code and (hopefully!) making it more maintainable in the long run.
However, here and there I'm hitting a bit of a wall where it seems neither interfaces nor abstract classes work for the reason that there are functions for which I want an implementation defined.
This means:
Interfaces will not work since I can't define an implementation and obviously don't want to repeat the code in all implementing classes
Abstract classes will not work because I cannot derive from multiple classes
Some super simple code to illustrate the problem:
public abstract class Vehicle
{
public void MoveForward()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueAbility(); // This is for the derived class to implement
}
public abstract class RadioSignalBroadcaster
{
public void StartBroadcast()
{
// Some code here
// This implementation is always the same
}
public abstract void PerformUniqueBroadcastingAbility(); // This is for the derived class to implement
}
Now of course what I'd like to do is this:
public class MyNewClass: Vehicle, RadioSignalBroadcaster
{
// Class that contains the implementations for both MoveForward() AND StartBroadcast() but also allows me to define
// bodys for the abstract methods
public override void PerformUniqueAbility()
{
// class specific code here
}
public override void PerformUniqueBroadcastingAbility()
{
// class specific code here
}
}
Of course I cannot do this because of the error:
Error CS1721 Class 'MyNewClass' cannot have multiple base classes: 'Vehicle' and 'RadioSignalBroadcaster'
What's the best way to approach these scenarios?
You could use interfaces with default implementations which were introduced in C# 8. Then you could derive from these interfaces.
Here's an example of how you could you provide default implementations for the MoveForward() and StartBroadcast() methods:
public interface IVehicle
{
void MoveForward()
{
// your code
}
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast()
{
// your code
}
void PerformUniqueBroadcastingAbility();
}
You can't inherit more than 1 class but you can inherit more than one interface. Is this what you are looking for?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
IVehicle vehicle = new Vehicle();
IRadioBroadcaster broadcaster = new RadioBroadcaster();
vehicle.MoveForward();
vehicle.PerformUniqueAbility();
broadcaster.StartBroadcast();
broadcaster.PerformUniqueAbility();
}
}
public interface IUniqueAbillity
{
void PerformUniqueAbility();
}
public interface IVehicle: IUniqueAbillity
{
void MoveForward();
}
public interface IRadioBroadcaster : IUniqueAbillity
{
void StartBroadcast();
}
public abstract class RealWorldObject : IVehicle, IRadioBroadcaster
{
public void MoveForward()
{
// Move forward
}
public abstract void PerformUniqueAbility();
public void StartBroadcast()
{
// Start broadcast
}
}
public class Vehicle : RealWorldObject, IVehicle
{
public override void PerformUniqueAbility()
{
// Do something
}
}
public class RadioBroadcaster : RealWorldObject, IRadioBroadcaster
{
public override void PerformUniqueAbility()
{
// Do something
}
}
}
C# classes can only inherit from one base class, but can inherit from any number of interfaces.
If your goal is to have multiple base classes being inherited to MyNewClass, you could change one of your abstract classes to inherit from the other, for example:
public abstract class RadioSignalBroadcast : Vehicle
{
// Implementation goes here
}
public class MyNewClass : RadioSignalBroacast
{
// Implementation goes here
}
However, as you can see from this approach, it violates Single Responsibility Principle as now RadioSignalBroadcast (and now MyNewClass) has more than one reason to change (if there's a change to Vehicle or RadioSignalBroadcast logic). Any change that happens to any of the base classes will propagate to all other classes which inherit from those base classes, which may or may not be what you're after.
What's the best way to approach these scenarios?
That entirely depends on the design of your application. Questions to ask yourself:
Do you require Vehicle and RadioSignalBroadcast to be abstract classes, or can it easily be an interface? By the looks of your implementation, you have a couple of methods which you want to share to your derived classes so I understand you wanting to keep them as base classes, but it's something to keep in mind. Also check out if the implementation of MoveForward and StartBroadcast can have a default interface implementation.
Does MyNewClass need to implement both base classes/interfaces? Couldn't two separate classes work out better? Separating out classes like this helps to focus each of the classes to have one single responsibility.
If MyNewClass is not truly a Vehicle or a RadioSignalBroadcast (as per the previous point), can this object be composed by a combination of either of the two, for example:
public class MyNewClass : Vehicle
{
private readonly RadioSignalBroadcast radio;
public MyNewClass(RadioSignalBroadcast radio)
{
this.radio = radio;
}
public void DoStuff()
{
// Do Stuff
this.radio.PerformUniqueBroadcastingAbility();
}
// Implementation goes here
}
Let me know if you want example or more points to point out.
I think Jonas gave you the best answer that you can use default interface implementations. However I keep my post, because it gives information, how to achieve same effect, using technology without this language feature.
public abstract class Example : IExample
{
private readonly IVehicle vehicle;
private readonly IRadioSignalBroadcaster;
public Example(IVehicle vehicle, IRadioSignalBroadcaster radioSignalBroadcaster)
{
this.vehicle = vehicle;
this.radioSignalBroadcaster = radioSignalBroadcaster;
}
public void MoveForward() => vehicle.MoveForward();
public void StartBroadcast() => radioSignalBroadcaster.StartBroadcast();
public void PerformUniqueAbility() => vehicle.PerformUniqueAbility();
public void PerformUniqueBroadcastingAbility() => radioSignalBroadcaster.PerformUniqueBroadcastingAbility();
}
public interface IExample : IVehicle, IRadioSignalBroadcaster
{
}
public interface IVehicle
{
void MoveForward();
void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
void StartBroadcast();
void PerformUniqueBroadcastingAbility();
}
public abstract class Vehicle : IVehicle
{
public void MoveForward()
{
// ...
}
public abstract void PerformUniqueAbility();
}
public interface ICustomVehicle : IVehicle
{
}
public class CustomVehicle : Vehicle, ICustomVehicle
{
public void PerformUniqueAbility()
{
// ...
}
}
public abstract class RadioSignalBroadcaster : IRadioSignalBroadcaster
{
public void StartBroadcast()
{
// ...
}
public abstract void PerformUniqueBroadcastingAbility();
}
public interface ICustomRadioSignalBroadcaster : IRadioSignalBroadcaster
{
}
public class CustomRadioSignalBroadcaster : RadioSignalBroadcaster, ICustomRadioSignalBroadcaster
{
public void PerformUniqueBroadcastingAbility()
{
// ...
}
}
You will create another classes like that:
public class CustomExample : Example, ICustomExample
{
public CustomExample(ICustomVehicle customVehicle, ICustomRadioSignalBroadcaster customRadioSignalBroadcaster) : base(customVehicle, customRadioSignalBroadcaster)
{
}
}
public interface ICustomExample : IExample
{
}
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>();
}
}
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 ();
}
}
I have an two interfaces defined as follows:
public interface IFoo
{
...
}
Public interface IFooWrapper<T> where T : IFoo
{
T Foo {get;}
}
I want to be able to declare a collection of IFooWrappers but I don't want to specify the implementation of IFoo.
Ideally I want to do something like the:
IList<IFooWrapper<*>> myList;
I can't figure out a way around this.
public interface IFoo
{
...
}
public interface IFooWrapper : IFoo
{
...
}
public interface IFooWrapper<T> : IFooWrapper
where T : IFoo
{
...
}
IList<IFooWrapper> myList;
this is a way to do what you want
What's wrong with
IList<IFooWrapper<IFoo>> myList?
public class FooWrapper : IFooWrapper<IFoo>
What I'm about to suggest is overkill for most situations, since usually you can create an interface higher up in the hierarchy that you can use. However, I think this is the most flexible solution in some ways, and the most faithful representation of what you want:
public interface IFooWrapperUser<U> {
U Use<T>(IFooWrapper<T> wrapper);
}
public interface IFooWrapperUser {
void Use<T>(IFooWrapper<T> wrapper);
}
public interface IExistsFooWrapper {
U Apply<U>(IFooWrapperUser<U> user);
void Apply(IFooWrapperUser user);
}
public class IExistsFooWrapper<T> : IExistsFooWrapper {
private IFooWrapper<T> wrapper;
public IExistsFoo(IFooWrapper<T> wrapper) {
this.wrapper = wrapper;
}
public U Apply<U>(IFooWrapperUser<U> user) {
return user.Use(foo);
}
public void Apply(IFooWrapperUser user) {
user.Use(foo)
}
}
Now you can create an instance of an IList<IExistsFooWrapper> which can be used as if it's an IList<IFooWrapper<*>>. The downside is you'll need to create a class to encapsulate the logic you want to run on each element:
private class FooPrinter : IFooWrapperUser<string> {
public string Apply<T>(IFooWrapper<T> wrapper) {
return wrapper.Foo.ToString();
}
}
...
IFooWrapperUser<string> user = new FooPrinter();
foreach (IExistFooWrapper wrapper in list) {
System.Console.WriteLine(wrapper.Apply(user));
}
...
I am getting this error:
type Bar does not implement interface IFoo
From this code:
public interface IFoo
{
void DoA();
void DoB();
}
public class Foo:IFoo
{
void IFoo.DoA()
{
}
void IFoo.DoB()
{
}
}
public class Bar:Foo
{
void IFoo.DoA()
{
base.doA();
}
void IFoo.DoB()
{
base.doB();
}
}
I am using C# 2.0.
What am I doing wrong?
public class Bar : Foo, IFoo
{
// Your code
}
I have run into this as well. what is 'worse', depending on how you look at it is you can't define the interface implementations to be virtual to be overridden in descendent classes. I have gotten into the habit of doing this:
public class Foo:IFoo
{
void IFoo.DoA()
{
DoACore();
}
void IFoo.DoB()
{
DoBCore();
}
protected virtual void DoACore()
{
}
protected virtual void DoBCore()
{
}
}
public class Bar:Foo
{ protected override void DoACore()
{
base.DoACore();
}
protected override void DoBCore()
{
base.DoBCore();
}
}
See n8wrl's answer as to how you should be doing this. See below for the reason why.
You can't explicity implement interface members (void IFoo.DoA()) when implicitly implementing the interface. In other words, because Bar only implements IFoo by virtue of extending Foo, you cannot use explicit implementation.
This will work:
public class Bar : Foo
{
public void DoA()
{
...
}
public void DoB()
{
...
}
Or this:
public class Bar : Foo, IFoo
{
void IFoo.DoA()
{
...
}
void IFoo.DoB()
{
...
}
A bigger problem that you'll probably face is that since Foo is not abstract, it must implement DoA and DoB. If you also implement these methods in bar, you will not be doing it polymorphically. You'll be hiding the Foo implementations if the code has a handle to the Bar type.
I would suspect the confusion arises over how interfaces were implemented in C++, as abstract classes and multiple inheritance.
In .NET, and interface is simply a contract that says you will implement those methods.
You're code won't compile for the same reason this code wont compile(it would with C++):
public interface IFoo
{
void DoSomething();
}
public abstract class Foo : IFoo
{
}
Foo is declaring that Foo implements IFoo, it doesn't say anything else about anyone.
If you wanted to force derived classes to implement it you would do:
public interface IFoo
{
void DoSomething();
}
public abstract class Foo : IFoo
{
public abstract void DoSomething();
}
Or if you really wanted the interface methods hidden by explicit implementation, then something like n8wrl posted above.
At first, this is not clear what is the task? If the goals was to fix a problem asap, than 'Bar : Foo, IFoo' is the shortest solution.
If you are just trying to learn 'implicit/explicit' interfaces difference, than check this post.
Also notice, that 'n8wrl' solution is arguable. It is ok only if Foo indeed required to implement IFoo explicitly. If no, than there is a simpler way:
public interface IFoo
{
void DoA();
}
public class Foo : IFoo
{
public virtual void DoA() {}
}
public class Bar : Foo
{
public override void DoA() {}
}
Hope this helps.