1

I have the following code where I want to downcast to an interface with generic but I get Run-time exception: Unable to cast object of type 'FinalAssociator' to type 'IAssociator`1[Common]'.

public interface ICommon 
{
    string Name {get;set;}
}
public class Common : ICommon 
{
    public string Name {get;set;}
}
public class FinalCommon : Common {}
public interface IAssociator<T> where T : ICommon
{
    void HandleEvent(T data);
}
public abstract class Associator<T> : IAssociator<T> where T : ICommon
{
    public abstract void HandleAnotherEvent(T data);
    public void HandleEvent(T data)
    {
        HandleAnotherEvent(data);
    }
}
public class FinalAssociator : Associator<FinalCommon>
{
    public override void HandleAnotherEvent(FinalCommon data)
    {
        Console.WriteLine(data.Name);
    }
}
var x = new FinalAssociator();
var y = new FinalCommon { Name = "John" };
var z = (IAssociator<Common>)x;
z.HandleEvent(y);
Ankan Kumar Giri
  • 243
  • 1
  • 3
  • 12

2 Answers2

2

You can't do this because it could lead to runtime errors due to invalid types, which is one of the things generics is intended to prevent. Consider what would happen if the compiler allowed your code. You have:

z.HandleEvent(y);

Here y is an instance of FinalCommon, which won't present a problem. However, what if you instead passed in something else, like:

z.HandleEvent(new Common());

This would result in your passing an instance of something that isn't FinalCommon to your method that is definitely expecting an instance of FinalCommon. This would be illegal, and the compiler prevents you from getting into this situation.

Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
0

FinalAssociatior inherits from Associator<FinalCommon>. Its HandleAnotherEvent method expects an argument of type FinalCommon.

If you could cast an instance of it as IAssociator<Common> then you'd be able to pass an argument of type Common to it, even though the class expects FinalCommon.

var finalAssociator = new FinalAssociator();
var commonAssociator = (IAssociator<Common>)finalAssociator; // can't do this

// You'd be able to do this because the interface allows it, but it doesn't
// make sense because the object is a FinalAssociator
// and it doesn't take this argument.
commonAssociator.HandleAnotherEvent(new Common()); 

As written, the compiler is unable to determine that this is invalid, which is why you get a runtime error. (Resharper provides a warning that this may fail at runtime.)

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62