Casting an implementation of Interface B to and implementation of Interface A - c#

I am trying to get code below running. I want to cast an object of class A to an object of class B, buit i get an error. In theory, the A is a part of B, so I can't see, why this won't work.
I know, that this cast does mean losing some data, but that is exactly what I want.
Is there any way to get this running?
public class Program
{
public static void Main()
{
var b = new B();
var a = (A)b; //Error: Cannot convert type
}
}
public interface IA{}
public interface IB : IA{}
public class A : IA{}
public class B : IB{}

Clearly, B is not of type A and vice versa:
It's impossible to cast B to A. You only can cast to IB or IA types.

You can solve this in multiple ways, one being the way Gilad Green stated in his answer, or by also implementing a conversion method:
public static implicit operator A(B b)
{
//your code to convert from B to A
}
public static implicit operator B(A a)
{
//your code to convert from A to B
}
Since B implements both IA and IB you cannot directly cast to and from one another unless you implement something like the code snippet in this answer.

Related

Containers of inherited objects

I have a simple class structure
abstract class A {
List<A> containerList;
...
}
class B : A {....}
class C : A {....}
I make sure that the containerList contains only elements of class B or C (as the list is filled in these child classes and A is abstract).
Now, I'd like, somehow, to have a base property / method in A which would cast itself to whatever the real type of the object is, i.e. B or C. Having an abstract method is just fine, but it is important to get a Collection<T> of B or C objects, as I have bindings that will depend on it.
Now, I'd like, somehow, to have a base property / method in A which would cast itself to whatever the real type of the object is, i.e. B or C.
I think you're mixing casting and converting. A Cast is a compile-time construct that just determines how methods and properties are bound at compile-time. It does not change the underlying object.
There's no conversion necessary because the object is already either a B or a C - since A is abstract you can't have an object that is actually an A.
So a method that returns the underlying collection as either a collection of Bs or Cs would just be:
public IEnumerable<B> GetBs()
{
return containerList.OfType<B>();
}
public IEnumerable<C> GetCs()
{
return containerList.OfType<C>();
}
If you want one generic method where the caller determines the type, you can do:
public IEnumerable<T> GetTs<T>() where T:A
{
return containerList.OfType<T>();
}
You could use generics like that (though it looks a little strange):
public abstract class A<T> where T : A<T>
{
protected List<A<T>> containerList;
public Collection<T> ContainerList
{
get { return new Collection<T>(containerList.OfType<T>().ToList()); }
}
}
public class B : A<B>
{
//...
}
public class C : A<C>
{
//...
}
But since containerList should only contain elements of the derived type, you can make it completely generic too like that:
protected List<T> containerList;
and could ommit the OfType() call:
public Collection<T> ContainerList { get { return new Collection<T>(containerList); }}
One drawback is that someone could have the idea to make a class D like that:
public class D : A<B>
{}
and would now have a class D with a ContainerList of type Collection<B>. But if it's that what he wants...
Instead of casting the objects in the list, you could use the is keyword (documentation link). When you need to operate on your List, just ask before doing your operation if (containerList[i] is B).

Can you attach an interface to a defined class

Here is the situation. In some cases I find myself wanting a class, let's call it class C that has the same functionalities as class A, but with the addition that it has interface B implemented. For now I do it like this:
class C : A,B
{
//code that implements interface B, and nothing else
}
The problem will come if class A happens to be sealed. Is there a way I can make class A implement interface B without having to define class C (with extension methods or something)
Basically: no. That is part of what "mixins" could bring to the table, but the C# languauge doesn't currently support that (it has been discussed a few times, IIRC).
You will have to use your current approach, or (more commonly) just a pass-through decorator that encapsulates A rather than inheriting A.
class C : IB
{
private readonly A a;
public C(A a) {
if(a == null) throw new ArgumentNullException("a");
this.a = a;
}
// methods of IB:
public int Foo() { return a.SomeMethod(); }
void IB.Bar() { a.SomeOtherMethod(); }
}
The only way I see, is to change inheritance to aggregation, like this:
class C : B
{
public C(A instanceToWrap)
{
this.innerA = instanceToWrap;
}
//coda that implements B
private A innerA;
}
There seems to be a possibility to inject interface in run-time, as it is done with Array class and IEnumerable<T> interface, but it seems a bit of an overkill.
Is there a way I can make class A implement interface B without having to define class C (with extension methods or something)
The short answer is no. You can't make A implement B because you don't have control of A. However, I think you're headed down the right road with extension methods. Consider this:
public static class AImplementsBExtensions
{
public static void Func1(this A o) { }
public static void Func2(this A o) { }
}
Now clearly I have no idea what methods exist on B, but this is how you can implement B on A when you can't inherit from it.
Bear in mind, this is not an implementation. If you add or remove methods from the interface you'll have to do that by hand here. But now you can do this:
var a = new A();
a.Func1();
You could try creating your class without the inheritance: class C : B and as a wrapper around A.
Additionally you can provide implicit conversion operators so that code like A obj = new C(new A()) would work similar to how a derived class would work.
class C : B
{
private A _inner;
public C(A inner)
{
this._inner = inner;
}
public A Inner { get { return this._inner; } }
public static implicit operator A(C obj)
{
return obj == null ? (A)null : obj._inner;
}
public static implicit operator C(A obj)
{
return new C(obj);
}
}

Class method that is not in the interface

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.

How to make some classes implement an interface while these classes are built into assembly

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.

Typing polymorphic values with multiple interfaces in 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.

Categories

Resources