I have a couple of classes which realize one method:
class ClassA : BaseClass
{
void Copy(ClassA a) {}
}
class ClassB : BaseClass
{
void Copy(ClassB b) {}
}
I want to describe these methods in the interface. Is it possible?
you can make use of Generic interface , for example as below
interface ICopy<T>
{
void Copy<T>(T t)
}
Class A: ICopy<A>,BaseClass//(if you need baseclass)
{
public void Copy(A a)
{}
}
Class B: ICopy<B>,BaseClass//(if you need baseclass)
{
public void Copy(B b)
{}
}
you can also try ICloneable inbuilt interface , if you just want to make clone of you class,
This is just suggestion
class Rock : ICloneable
{
int _weight;
bool _round;
bool _mossy;
public Rock(int weight, bool round, bool mossy)
{
this._weight = weight;
this._round = round;
this._mossy = mossy;
}
public object Clone()
{
return new Rock(this._weight, this._round, this._mossy);
}
}
Use a generic interface. Using where you can constrain the type parameter T to BaseClass and its derived types.
interface Interface<T> where T : BaseClass
{
void Copy<T>(T t);
}
class ClassA : BaseClass, Interface<ClassA>
{
public void Copy(ClassA b) {}
}
class ClassB : BaseClass, Interface<ClassB>
{
public void Copy(ClassB b) {}
}
Related
Why i can't convert implementation of interface which concrete implement generic interface? I need for Cat, Dog etc own interface realisation.
public interface IMarker { }
public class ResultA : IMarker
{
}
public class ResultB : IMarker
{ }
public interface IService<T> where T : IMarker
{
public List<T> DoStuff();
}
public interface ICatService : IService<ResultA>
{ }
public interface IDogService : IService<ResultB>
{ }
public class CatService : ICatService
{
public List<ResultA> DoStuff()
{
return new List<ResultA>();
}
}
public class DogService : IDogService
{
public List<ResultB> DoStuff()
{
return new List<ResultB>();
}
}
public abstract class Animal
{
protected readonly IService<IMarker> _svc;
protected Animal(IService<IMarker> svc)
{
_svc = svc;
}
}
public class Cat : Animal
{
public Cat(ICatService svc) : base(svc)
{
}
}
public class Dog : Animal
{
public Dog(ICatService svc) : base(svc)
{
}
}
CS1503 Argument 2: cannot convert from 'ICatService' to 'IService'
I have DI for services i.e. :
services.AddTransient<ICatService, CatService>();
The reason for such behaviour is that in general case IService<ResultA> is not IService<IMarker> (basically I would argue the same cause for C# classes does not supporting variance which is for a pretty good reason - see more here and here).
In this concrete case everything can be fixed by making the interface covariant and leveraging the covariance of IEnumerable<T>:
public interface IService<out T> where T : IMarker
{
public IEnumerable<T> DoStuff();
}
public class CatService : ICatService
{
public IEnumerable<ResultA> DoStuff() => return new List<ResultA>();
}
public class Cat : Animal
{
public Cat(CatService svc) : base(svc)
{
}
}
But not sure that in your actual code you will be able to.
Or just make the base class generic (if this suits your use case):
public abstract class Animal<T> where T : IMarker
{
protected readonly IService<T> _svc;
protected Animal(IService<T> svc)
{
_svc = svc;
}
}
Original answer
CatService does not implement ICatService, i.e. the fact that ICatService inherits only IService<ResultA> does not mean that they are the same, C# is strongly-typed (mostly :-) language and compiler will consider those two interfaces being different ones (though related). You need either to make CatService to implement ICatService:
public class CatService : ICatService
{
// ...
}
Or register and resolve the IService<ResultA> interface (basically skipping intermediate interface at all):
services.AddTransient<IService<ResultA>, CatService>();
// ...
public Cat(IService<ResultA> svc) : base(svc){}
I have two trees of classes with generics and I cannot figure out one thing, that I know how to solve in Java with <? extends ...>.
First AI tree:
abstract class AbstractAI<TCtrl> : MonoBehaviour where TCtrl: IRotableWeaponController
abstract class AbstractShipAI : AbstractAI<IShipController>
class ModularAI : AbstractShipAI
Some other classes that extend AbstractAI and use various modules
Modules tree:
abstract class AbstractModule<TAi, TCtrl> : AIModule where TAi: AbstractAI<TCtrl> where TCtrl: IRotableWeaponController
{
public virtual void Init(TAi parent)
}
class ShootModule: AbstractModule<AbstractAI<IRotableWeaponController>, IRotableWeaponController>
Some other modules that extend AbstractModule and can be used only with some AIs, that have required capabilities
Used controller interfaces tree:
interface IRotableWeaponController
interface IShipController: IRotableWeaponController
Other interfaces extending IRotableWeaponController...
The issue is:
class ModularAI : AbstractShipAI
{
public ShootModule shootModule;
protected override void Start()
{
shootModule.Init(this); // Error: Argument type 'ModularAI' is not assignable to parameter type 'AbstractAI<IRotableWeaponController>'
}
}
ModularAI is AbstractAI<IShipController>, IShipController is IRotableWeaponController, but I get an error.
In Java I would do:
abstract class AbstractModule<TAi, TCtrl> : AIModule where TAi: AbstractAI<? extends TCtrl> where TCtrl: IRotableWeaponController
I know it's kind of complex and there is probably a better way to design it (and I may eventually get to it one day) but I want to know, how to solve this issue.
Please, how can I make it work?
I made an easier example to illustrate your issue :
class Fruit { }
class Apple : Fruit { }
class FruitMaker<T> where T : Fruit { }
class Program
{
static void HandleFruit(FruitMaker<Fruit> fruitMaker) { }
static void Main()
{
FruitMaker<Apple> appelMaker = new FruitMaker<Apple>();
FruitMaker<Fruit> fruitMaker = appelMaker; //cannot convert from 'FruitMaker<Apple>' to 'FruitMaker<Fruit>'
HandleFruit(fruitMaker);
}
}
What you need is generics covariance, you need to pass FruitMaker<Apple> to a method that expects FruitMaker<Fruit>.
This is enabled with the out keyword, what you want is class FruitMaker<out T> where T : Fruit { }, but you can't do that because FruitMaker is not an interface. You can solve this as follows :
class Fruit { }
class Apple : Fruit { }
interface IFruitMaker<out T> where T : Fruit { }
class FruitMaker<T> : IFruitMaker<T> where T : Fruit { }
class Program
{
static void HandleFruit(IFruitMaker<Fruit> fruitMaker) { }
static void Main()
{
FruitMaker<Apple> appelMaker = new FruitMaker<Apple>();
IFruitMaker<Fruit> fruitMaker = appelMaker; //this is allowed thanks to the out keyword
HandleFruit(fruitMaker);
}
}
Notice that I introduced an interface just to be able to add the out keywork.
You can use Covariance by inserting an interface in place of the abstract class, appropriately marked for it:
interface IAbstractAI<out TCtrl> where TCtrl : IRotableWeaponController {
}
abstract class AbstractAI<TCtrl> : MonoBehaviour, IAbstractAI<TCtrl> where TCtrl : IRotableWeaponController {
}
abstract class AbstractModule<TAi, TCtrl> : AIModule where TAi : IAbstractAI<TCtrl> where TCtrl : IRotableWeaponController {
public virtual void Init(TAi parent) {
}
}
class ShootModule : AbstractModule<IAbstractAI<IRotableWeaponController>, IRotableWeaponController> {
}
class ModularAI : AbstractShipAI {
public ShootModule shootModule;
protected override void Start() {
shootModule.Init(this); // Error: Argument type 'ModularAI' is not assignable to parameter type 'AbstractAI<IRotableWeaponController>'
}
}
I have an abstract class which should have a method returning an instance of a class which should inherit from a base class as well implement an interface.
public abstract class AbstractClass
{
abstract [DonotKnowTheType] GetClassInstance() //The Return type should be an instance of a class which implements TestClass and ISample
}
public class ChildClass : AbstractClass
{
override [DonotKnowTheType] GetClassInstance()
{
//Need to return instance of SampleClass in this example. This could vary, this should be an instance of a class which implements TestClass and ISample
}
}
public class SampleClass : TestClass,ISample
{
//Implementation
}
Please help to achieve this with a good design. Need to restrict developers who writes the overriding method in ChildClass to return only an instance of a class which implements TestClass and ISample. If not, it has to show a compile time error.
You could make your abstract class generic with a contraint on TestClass and ISample:
public abstract class AbstractClass<T> where T: TestClass, ISample
{
public abstract T GetClassInstance(); //The Return type should be an instance of a class which implements AbstractClass and ISample
}
public class ChildClass : AbstractClass<SampleClass>
{
public override SampleClass GetClassInstance()
{
//Need to return instance of SampleClass in this example. This could vary, this should be an instance of a class which implements AbstractClass and ISample
return new SampleClass();
}
}
Try this:
public abstract class TheEnforcer<T> where T: TestClass, IMyInterface
{
protected abstract T GetClassInstance();
}
public class ThePoorClass : TheEnforcer<DerivedTestClass>
{
protected override DerivedTestClass GetClassInstance()
{
throw new NotImplementedException();
}
}
public class TestClass
{
}
public class DerivedTestClass : TestClass, IMyInterface
{
}
public interface IMyInterface
{
}
After your comment:
namespace First {
public abstract class TheEnforcer<T> where T : IMarkerInterface
{
protected abstract T GetClassInstance();
}
public interface IMarkerInterface
{
} }
namespace Second {
using First;
// All this is in separate name space
public class TestClass: IMarkerInterface
{
}
public class DerivedTestClass : TestClass, IMyInterface
{
}
public interface IMyInterface
{
}
public class ThePoorClass : TheEnforcer<DerivedTestClass>
{
protected override DerivedTestClass GetClassInstance()
{
throw new NotImplementedException();
}
} }
I have a base abstract class that also implements a particular interface.
public interface IMovable<TEntity, T>
where TEntity: class
where T: struct
{
TEntity Move(IMover<T> moverProvider);
}
public abstract class Animal : IMovable<Animal, int>
{
...
public virtual Animal Move(IMover<int> moverProvider)
{
// performs movement using provided mover
}
}
Then I have inherited classes some of which have to override interface implementation methods of the base class.
public class Snake : Animal
{
...
public override Animal Move(IMover<int> moverProvider)
{
// perform different movement
}
}
My interface methods return the same object instance after it's moved so I can use chaining or do something directly in return statement without using additional variables.
// I don't want this if methods would be void typed
var s = GetMySnake();
s.Move(provider);
return s;
// I don't want this either if at all possible
return (Snake)GetMySnake().Move(provider);
// I simply want this
return GetMySnake().Move(provider);
Question
As you can see in my example my overrides in child class returns base class type instead of running class. This may require me to cast results, which I'd like to avoid.
How can I define my interface and implementations so that my overrides will return the actual type of the executing instance?
public Snake Move(IMover<int> moverProvider) {}
I suggest changing the return type of the interface method to void and moving the chaining behaviour to an extension method where you can get the real type of the target e.g.
public interface IMovable<TEntity, T>
where TEntity : class
where T : struct
{
void MoveTo(IMover<T> moverProvider);
}
public abstract class Animal : IMovable<Animal, int>
{
public virtual void MoveTo(IMover<int> mover) { }
}
public static class AnimalExtensions
{
public static TAnimal Move<TAnimal>(this TAnimal animal, IMover<int> mover) where TAnimal : Animal, IMovable<TAnimal, int>
{
animal.MoveTo(mover);
return animal;
}
}
Note you can make the Move extension more generic if you need it to apply more generally:
public static TEntity Move<TEntity, T>(this TEntity entity, IMover<T> mover) where TEntity : IMovable<TEntity, T> where T : struct
{
entity.MoveTo(mover);
return entity;
}
You can convert Animal to a generic type that accepts the concrete type as a type parameter:
public abstract class Animal<T> : IMovable<T, int> where T:Animal<T>
{
public virtual T Move(IMover<int> moverProvider)
{
...
}
}
public class Snake : Animal<Snake>
{
public override Snake Move(IMover<int> moverProvider)
{
...
}
}
How about:
public virtual T Move<T>(IMover<int> moverProvider) where T : Animal
{
// performs movement using provided mover
}
Sometimes you need to have current type as method return value and it has to change in derived classes. I'd avoid this pattern because it'll lead to strange behaviors and unusual syntax (if your model becomes complex) but give it a try (primary because for very small hierarchies it looks pretty simple):
abstract class Animal<TConcrete> : IMovable<TConcrete, int>
where TConcrete : Animal<T>
{
public virtual T Move(IMover<int> moverProvider) {
return (T)this; // Cast to Animal<T> to T isn't implicit
}
}
sealed class Snake : Animal<Snake>
{
public virtual Snake Move(IMover<int> moverProvider) {
return this;
}
}
Why is this bad? You can answer yourself when you'll need to declare a generic variable of type Animal<TConcrete> (in practice this stops you to have a variable with that base class).
What I'd do is to make this requirement clear (with a class or an extension method - in this case using another name):
abstract class Animal : IMovable<Animal, int>
{
// Please note that this implementation is explicit
Animal IMovable<Animal, int>.Move(IMover<int> moverProvider) {
return MoveThisAnimal(moverProvider);
}
protected virtual Animal MoveThisAnimal(IMover<int> moverProvider) {
// Peform moving
return this;
}
}
class Snake : Animal
{
public Snake Move(IMover<int> moverProvider) {
return (Snake)MoveThisAnimal(moverProvider);
}
protected override Animal MoveThisAnimal(IMover<int> moverProvider) {
// Peform custom snake moving
return this;
}
}
It's messy, but by introducing a non-generic base interface, an extension method can give the desired result. It can also be simplified (to remove the second explicit interface implementation) if you don't care about exposing the 'MoveFunc' to callers:
public interface IMovable
{
IMovable MoveFunc();
}
public interface IMovable<TEntity, T> : IMovable
where TEntity : IMovable
{
new TEntity MoveFunc();
}
public abstract class Animal : IMovable<Animal, int>
{
protected virtual Animal MoveFunc()
{
// performs movement using provided mover
Debug.WriteLine("Animal");
}
Animal IMovable<Animal, int>.MoveFunc()
{
return MoveFunc();
}
IMovable IMovable.MoveFunc()
{
return ((IMovable<Animal, int>)this).MoveFunc();
}
}
public class Snake : Animal
{
protected override Animal MoveFunc()
{
// performs movement using provided mover
Debug.WriteLine("Snake");
}
}
public static class IMovableExtensions
{
public static TOut Move<TOut>(this TOut entity) where TOut : IMovable
{
return (TOut)entity.MoveFunc();
}
}
...
Snake snake = new Snake();
Snake moved = snake.Move(); // "Snake"
Animal animal = snake;
animal.Move() // "Snake"
This question seems weird, but i came across this question in one of the interviews recently.
I ve been asked, is there a way in c# to hide the methods partially in a inherited child classes?. Assume the base class A, exposed 4 methods. Class B implements A and it will only have the access to first 2 methods and Class C implements A will only have the access to last 2 methods.
I know we can do this way
public interface IFirstOne
{
void method1();
void method2();
}
public interface ISecondOne
{
void method3();
void method4();
}
class baseClass : IFirstOne, ISecondOne
{
#region IFirstOne Members
public void method1()
{
throw new NotImplementedException();
}
public void method2()
{
throw new NotImplementedException();
}
#endregion
#region ISecondOne Members
public void method3()
{
throw new NotImplementedException();
}
public void method4()
{
throw new NotImplementedException();
}
#endregion
}
class firstChild<T> where T : IFirstOne, new()
{
public void DoTest()
{
T objt = new T();
objt.method1();
objt.method2();
}
}
class secondChild<T> where T : ISecondOne, new()
{
public void DoTest()
{
T objt = new T();
objt.method3();
objt.method4();
}
}
But what they wanted is different. They wanted to hide these classes on inheriting from baseclasses. something like this
class baseClass : IFirstOne, ISecondOne
{
#region IFirstOne Members
baseClass()
{
}
public void method1()
{
throw new NotImplementedException();
}
public void method2()
{
throw new NotImplementedException();
}
#endregion
#region ISecondOne Members
public void method3()
{
throw new NotImplementedException();
}
public void method4()
{
throw new NotImplementedException();
}
#endregion
}
class firstChild : baseClass.IFirstOne //I know this syntax is weird, but something similar in the functionality
{
public void DoTest()
{
method1();
method2();
}
}
class secondChild : baseClass.ISecondOne
{
public void DoTest()
{
method3();
method4();
}
}
is there a way in c# we can achieve something like this...
I did it by having 1 main base class and 2 sub bases.
// Start with Base class of all methods
public class MyBase
{
protected void Method1()
{
}
protected void Method2()
{
}
protected void Method3()
{
}
protected void Method4()
{
}
}
// Create a A base class only exposing the methods that are allowed to the A class
public class MyBaseA : MyBase
{
public new void Method1()
{
base.Method1();
}
public new void Method2()
{
base.Method2();
}
}
// Create a A base class only exposing the methods that are allowed to the B class
public class MyBaseB : MyBase
{
public new void Method3()
{
base.Method3();
}
public new void Method4()
{
base.Method4();
}
}
// Create classes A and B
public class A : MyBaseA {}
public class B : MyBaseB {}
public class MyClass
{
void Test()
{
A a = new A();
// No access to Method 3 or 4
a.Method1();
a.Method2();
B b = new B();
// No Access to 1 or 2
b.Method3();
b.Method4();
}
}
Although you can't do exactly what you want, you could use explicit interface implementation to help, in which the interface members are only exposed if it is explicitly cast to that interface...
Perhaps the interviewer may have been referring to method hiding?
This is where you declare a method with the same signature as on in your base class - but you do not use the override keyword (either because you don't or you can't - as when the method in the base class is non-virtual).
Method hiding, as opposed to overriding, allows you to define a completely different method - one that is only callable through a reference to the derived class. If called through a reference to the base class you will call the original method on the base class.
Don't use inheritance. It makes the public or protected facilities of the base class available directly in the derived class, so it simply isn't want you want.
Instead, make the derived class implement the relevant interface, and (if necessary) forward the methods on to a private instance of the underlying class. That is, use composition (or "aggregation") instead of inheritance to extend the original class.
class firstChild : IFirstOne
{
private baseClass _owned = new baseClass();
public void method1() { _owned.method1(); }
// etc.
}
By the way, class names should start with an upper case letter.
There is 2 solutions to hide methods inherited from a base class:
As mentioned by thecoop, you can explicitely implement the interface declaring the methods you want to hide.
Or you can simply create these methods in the base class (not inherited from any interface) and mark them as private.
Regards.
What about injecting base class as an IFirst?
interface IFirst {
void method1();
void method2();
}
interface ISecond {
void method3();
void method4();
}
abstract class Base : IFirst, ISecond {
public abstract void method1();
public abstract void method2();
public abstract void method3();
public abstract void method4();
}
class FirstChild : IFirst {
private readonly IFirst _first;
public FirstChild(IFirst first) {
_first = first;
}
public void method1() { _first.method1(); }
public void method2() { _first.method2(); }
}
Injection keeps you from violating the Interface Segregation Principle. Pure inheritance means that your FirstChild is depending on an interface that it doesn't use. If you want to retain only the IFirst functionality in Base, but ignore the rest of it, then you cannot purely inherit from Base.