R
R
Ruslan2021-12-23 10:38:07
.NET
Ruslan, 2021-12-23 10:38:07

Why doesn't interface typecasting work?

Hello.
In a certain case, there is no conversion (cast) of an interface to a class.
To begin with, a typical working example:

There is an interface, there is an implementing class, there is another class with a static method that receives an interface as input and receives a class name through reflection. This method also performs a cast of the interface to the type and accesses the property defined in the type.

public interface ITest { }

public class CTest : ITest
{
    public string Message { get; set; }
}

public class Testing
{
    public static void DoIt(ITest t)
    {
        Console.WriteLine(t.GetType().Name);//->CTest
        CTest ct = (CTest)t;
        Console.WriteLine(ct.Message);//->test message
    }
}


In the Main method of the console application, the following code is called:

CTest t=new CTest(){ Message = "test message"};
Testing.DoIt(t);


expected result:

CTest
test message

---------------------

Now a strange example, which I ask you to explain.

There is a Nuget package MassTransit (7.3.0) ( https://github.com/MassTransit/MassTransit )
There is an interface Fault, it is inherited from it, a class is inherited from it somewhere in the bowels of the code a class is instantiated (we cannot create an object interface) and then it is passed as an input parameter to my method:Fault<out T>FaultEvent<T>

public Task Consume(ConsumeContext<Fault> context)
{
    Fault m = context.Message;
    string typename = m.GetType().FullName;
}


The typename variable contains the value: "GreenPipes.DynamicInternal.MassTransit.Fault", i.e. the value of an interface, not a class. It turns out that this code managed to create the interface object.

Can someone explain how this is possible?
Thank you.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
ayazer, 2021-12-24
@Razbezhkin

https://github.com/MassTransit/MassTransit/blob/5e...
this is not the Fault you are thinking about. Somewhere in the bowels of GreenPipes there is another Fault class. So no magic happened -

using MassTransit;
using System;

namespace GreenPipes.DynamicInternal.MassTransit
{
    public class MyFault<T> : Fault<T>
    {
        public T Message => throw new NotImplementedException();

        public Guid FaultId => throw new NotImplementedException();

        public Guid? FaultedMessageId => throw new NotImplementedException();

        public DateTime Timestamp => throw new NotImplementedException();

        public ExceptionInfo[] Exceptions => throw new NotImplementedException();

        public HostInfo Host => throw new NotImplementedException();

        public string[] FaultMessageTypes => throw new NotImplementedException();
    }

    public class Fault: MyFault<object>
    {

    }


    public class Program
    {
        static void Main(string[] args)
        {
            var fault = new Fault();

            string typename = fault.GetType().FullName; //GreenPipes.DynamicInternal.MassTransit.Fault

        }
    }
}

V
Vlad, 2022-01-03
@KislyFan

Because that's the way it is here. When you do so void DoIt(ITest t) you are not passing an interface, but an implementation. For example, the same CTest, or its descendant, which can naturally be formalized or reduced to CTest. And so ayazer is right

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question