I made a bad mistake in trying to design a framework where one class would inherit two others; forgetting that C# doesn't have multiple inheritance. Because of this error, I made a workaround.
A : B
Both : A //Now has all members of both A and B, unless they're hidden
If A and B both have a member by the same name, can I access the member of B (hidden by A) without changing the framework, and if so, how?
Edit: Classes A and B are not meant to be instantiated.
One approach you could take is to extract the method into a pair of interfaces and use explicit interface implementations in classes A, B.
interface IA {
void Method();
}
interface IB {
void Method();
}
abstract class B : IB {
void IB.Method() { ... }
}
abstract class A : B, IA {
void IA.Method() { ... }
}
class Both : A { ... }
You must then cast to the interface to access the methods, and attempting to call Method without the cast results in a compile time error.
Both x = new Both();
((IA)x).Method();
((IB)x).Method();
x.Method() //invalid call
C c = new C();
c.Member("This is C's version, if there is one; otherwise it's A's");
((A)c).Member("This is A's version");
((B)c).Member("This is B's version");
Related
Imagine a situation where two marker interfaces A and B guard single Base interface:
interface Base
{
void Hello();
}
interface A: Base
{
}
interface B: Base
{
}
Is there a way to define class C that implements both A and B while providing marker interface specific Hello implementations? Note that Base, A and B interfaces are declared in an external library so I could not modify it.
If I do this
class C: A, B
{
void A.Hello() =>
Console.Out.WriteLine("A");
void B.Hello() =>
Console.Out.WriteLine("B");
}
...it results in CS0539 compiler error:
member in explicit interface declaration is not a member of interface.
No, it's not possible in C# without modifying the interfaces. The only explicit interface implementation that is possible is Base.Hello:
class C: A, B
{
void Base.Hello() =>
Console.Out.WriteLine("Base");
}
I have a simple c# question (so I believe). I'm a beginner with the language and I ran into a problem regarding interfaces and classes that implement them. The problem is
I have the Interface iA
interface iA
{
bool method1
bool method2
bool method3
}
and 3 classes that implement the interface: class B, C and D
class B : iA
{
public bool method1
public bool method2
public bool method3
}
if class B had another method that is not in the interface, let's say method4() and I have the following:
iA element = new B();
and then I would use :
element.method4();
I would get an error saying that I don't have a method4() that takes a first argument of type iA.
The question is: Can I have an object of interface type and instantiated with a class and have that object call a method from the class, a method that is not in the interface ?
A solution I came up with was to use an abstract class between the interface and the derived classes, but IMO that would put the interface out of scope. In my design I would like to use only the interface and the derived classes.
Yes, that is possible. You just need to cast the Interface type to the class type like this:
iA element = new B();
((B)element).method4();
As suggested by wudzik, you should check if elemnt is of the correct type:
if(element is B)
{
((B)element).method4();
}
You have to cast the interface type to the class type; usually we do it by means of as:
B b = element as B; // <- try cast element as B
if (!Object.RefernceEquals(null, b)) { // <- element is B or can be legaly interpreted as B
b.method4();
}
The advantage of "as" is that there's only one cast operation, while "is" and (B) have to do two casts.
Without casting you could do this.
interface iA
{
bool method1();
bool method2();
bool method3();
}
interface IFoo : iA
{
bool method4();
}
class B : IFoo
{
public bool method1() {}
public bool method2() {}
public bool method3() {}
public bool method4() {}
}
IFoo element = new B();
element.method4();
NB: Try to use capital I prefix for C# interfaces.
What I mean is that for example, there are class A, class B and class C. A, B, C all have a method void M(), but none of them are declared implemented any interface.
So I give an interface with a void M() constraint. But the class A, B, C are types in a assembly.
Is there any way to use those class as if they are already implemented an interface.
No, you can't modify existing classes this way.
You can derive new classes and say they implement new interface. Existing methods in base class will be picked as interface implementation.
interface IWithM
{
void M();
}
class MyA : A, IWithM
{
// IWithM.M will be picked from A.M
}
No, there is no way to do that.
You could, however, write adapter classes that inherit from A, B and C and implement the interface.
public class AAdapter : A, IMyInterface
{
}
With the decorator pattern.
You could create your own version of these classes and then decorate the implementation, without modifing the assembly owned by someone else.
Your interface:
public interface IImplementsM()
{
void M();
}
public class MyA : IImplementsM
{
private A _a;
public MyA(A a){
_a = a;
}
public void M(){
_a.M();
}
}
Then in your code instead of using A you can use your own version or the Interface.
// some other class
public void DoSomething(IImplementsM implementsM)
{
implementsM.M();
}
And to execute could be something like:
var myA = new MyA(new A());
DoSomething(myA);
Advantage, you can now have a contraint when working in your own code.
Distadvantage, you have to then use your version of the class in your assembly, not theirs.
I have a Base class and 2 derived classes. I have a variable of base class which can hold one of the derived classes. I want to send that variable to a method which receives derived classes.
What can I do to resolve this problem without explicit cast since I don't know what the variable holds?
code:
Class A{
virtual public void foo1() {/.../}
}
Class B : A{
override public void foo1() {/.../}
}
Class C : A{
override public void foo1() {/.../}
}
Class D{
public foo(B argB) {/.../}
public foo(C argC) {/.../}
// in main
D varD = new D();
A varA = new B();
varD.foo(varA); //--->> Problem here need explicit casting
A varC = new C();
varD.foo(varC); //--->> Problem here need explicit casting
I don't know what derived class I'm sending to varD.foo and I want different handling of different derived classes. What can I do?
This is not what polymorphism is about - you can not pass a base class where a specialized class is expected, even when explicitly casting. Polymorphism works the other way: You can pass a specialized class wherever the base class is expected.
What you should do is make D.foo expect A and you will automatically be fine. If you add any methods to B or C which have no base implementation in A, you need to pass B anyway and can not cast an A to B or D.
Just make foo an abstract instance method of A and override the implementation in B and C. You could even keep your class D and delegate the actual work to there but it depends if this is a good idea.
Here the code with delegation to D. Also note that I omitted the method foo1() in all classes.
public abstract class A
{
public abstract void foo(D d);
}
public sealed class B : A
{
public override void foo(D d)
{
d.foo(this);
}
}
public sealed class C : A
{
public override void foo(D d)
{
d.foo(this);
}
}
public sealed class D
{
public void foo(B b) { [...] }
public void foo(C c) { [...] }
}
Now you can use virtual method dispatching to call the correct method.
D d = new D();
A b = new B();
A c = new C();
b.foo(d); // Calls B.foo(D) and in turn D.foo(B).
c.foo(d); // Calls C.foo(D) and in turn D.foo(C).
Is there any type-safe, compile-time checked possibilty of referring to values that implement multiple interfaces?
Given
interface A {
void DoA();
}
interface B {
void DoB();
}
I'm able to write code for objects implementing A or B, but not both. So I've to come up with ugly wrappers:
class ABCollection {
private class ABWrapper : A, B {
private readonly A a;
private readonly B b;
public static ABWrapper Create<T>(T x) where T : A, B {
return new ABWrapper { a = x, b = x };
}
public void DoA() {
a.DoA();
}
public void DoB() {
b.DoB();
}
}
private List<ABWrapper> data = new List<ABWrapper>();
public void Add<T>(T val) where T : A, B {
data.Add(ABWrapper.Create(val));
}
}
Is there a trick to write this code more intuitively without losing type-safety (runtime-casts etc.)?
E.g.
private List<A and B> ...
Edit: This is not about having a list in particular - I just wanted to give a "complete" example with the issue of storing such values. My problem is just how to type a combination of both interfaces (like A & B or A and B).
Another more useful example: List<IDrawable & IMovable> ...
You can do parametric polymorphism like that in C#, but not subtype polymorphism. That is, you can create a polymorphic method like:
void Foo<T>(T t) where T : IFoo, IBar
{
t.Foo();
t.Bar();
}
and then you must pass an object whose type is known at compile time to implement both IFoo and IBar.
But there is no way to say
void Foo(IFoo-and-IBar t)
{
t.Foo();
t.Bar();
}
and then pass in a value that is both an IFoo and an IBar. Neat feature, but not one we support.
Well, as Eric Lippert said, there's no IFoo-and-IBar type you can use as a method parameter type.
However, I was playing around with some ideas and came up with an alternate way of using your wrapper class that may be better. I'll leave that up to you (or whoever else might search for this question) to decide:
CLASSES
public abstract class ABWrapper : IA, IB
{
private readonly IA a;
private readonly IB b;
protected ABWrapper( IA a, IB b ) { this.a = a; this.b = b; }
// Implement methods on IA and IB
}
public sealed class ABWrapper<T> : ABWrapper
where T : IA, IB
{
private ABWrapper( T a, T b ) : base( a, b ) { }
public static implicit operator ABWrapper<T>( T t )
{
if ( t == null ) return null;
return new ABWrapper<T>( t, t );
}
}
EXAMPLE
public class AB : IA, IB { }
void Method( ABWrapper x )
{
}
void Main()
{
AB x = null;
Method( (ABWrapper<AB>) x );
}
The icky thing about this is that you need to do a cast to ABWrapper<T> at every call site. You could also create an extension method ABWrapper ToABWrapper<T>(this T t) where T : IA, IB to replace the cast if that would be more preferable.
It would be cool if the compiler could reason that an implicit conversion from AB to ABWrapper exists via implicit conversions to and from ABWrapper<T>. There's probably a very good reason it doesn't try to do that, however.
However, what you gain is the ability to put ABWrapper all throughout your method parameters without needing to genercize the methods.
I'm not clear on why you'd want to do this. If you did, you could declare a base interface:
interface AorB {}
interface A : AorB {
void DoA();
}
interface B : AorB {
void DoB();
}
and store those in the collection. Of course you'd have to is- or as-cast when retrieving (standard extension methods could help here).
It seems to me that this is a possible violation of SRP, and the collection is doing too much. Alternately the interfaces are too finely-grained.