user2944295
user2944295

Reputation: 57

C#: Is there a way to cast a class to an interface it implements at runtime, but not compile time?

If I have a base class and a couple derived classes that implement an interface, e.g.:

public class BaseClass
{

}

public interface IInterface
{
    void SomeMethod();
}

public class DerivedA : BaseClass, IInterface
{
    public void SomeMethod()
    {
        // some implementation
    }
}
public class DerivedB: BaseClass, IInterface
{
    public void SomeMethod()
    {
        // some other implementation
    }
}

And I have an unrelated class that has a BaseClass field:

public class UnrelatedClass
{
    public BaseClass foo;
}

Provided my implementation assumes foo should be some derived class that does implement the interface (but I don't know which so I can't just cast to that class), can I somehow cast it to IInterface and call foo.SomeMethod() without generating a compile error?

P.S.- I know this is a really roundabout way to do this and should just use an "IInterface foo" field instead, but due to Unity not serializing interface fields and not wanting to write a custom inspector- this is a workaround I'm trying.

Upvotes: 0

Views: 95

Answers (3)

CodingYoshi
CodingYoshi

Reputation: 27009

Right now your BaseClass has no point in your design. If you were to change your design a little bit, then you may not even need to perform checks at runtime. Here is a proposed design wherein BaseClass implements IInterface and derived classes need to override it:

public interface IInterface
{
    void SomeMethod();
}

public abstract class BaseClass : IInterface
{
    public abstract void SomeMethod();
    // Or virtual with common implementation
}

public class DerivedA : BaseClass
{
    public override void SomeMethod()
    {
        // some implementation
    }
}
public class DerivedB : BaseClass
{
    public override void SomeMethod()
    {
        // some other implementation
    }
}

Upvotes: 0

Sweeper
Sweeper

Reputation: 271150

I will provide a solution by changing your design. I guess your ultimate goal is that you want your foo object to have all the members of BaseClass and IInterface. You can create an abstract class like so:

abstract class BaseClassAndInterface: BaseClass, IInterface {
    public abstract void SomeMethod();
}

Now make DerivedA and DerivedB inherit from BaseClassAndInterface and implement the method in the interface.

public class DerivedA : BaseClassAndInterface
{
    public override void SomeMethod()
    {
        // some implementation
    }
}
public class DerivedB: BaseClassAndInterface
{
    public override void SomeMethod()
    {
        // some other implementation
    }
}

Now, foo can be declared as BaseClassAndInterface.

Upvotes: 0

Michael
Michael

Reputation: 2113

You can access the interface method via reflection (slow!) or you can 'safe- cast' with the as operator. The as operator 'returns' null if the cast fails. Like this:

var impl = foo as IInterface;
impl?.SomeMethod()
// or if(impl != null) impl.SomeMethod();

Upvotes: 3

Related Questions