【问题标题】:Why cannot I cast an object to its interface type?为什么我不能将对象转换为它的接口类型?
【发布时间】:2020-03-13 15:25:22
【问题描述】:

我有一个简单的课程

public class Message<T>
{
    public T Item { get; set; }

    public Message(T item)
    {
        Item = item;
    }
}

我想为另一组类创建一个基本类型 BaseEvent,有一个方法 ToMessage 可以转换为消息类,例如:

IConcreteEvent event = new ConcreteEvent(...);
Message<IConcreteEvent> = event.ToMessage();

拥有Message&lt;T&gt; 泛型类型的接口很重要,因为该对象将通过网络服务发送。

我做了类似的事情

public interface IBaseEvent<T>
{
    Message<T> ToMessage();
}

public class BaseEvent<T> : IBaseEvent<T>
{
    public Message<T> ToMessage()
    {
        return new Message<T>((T)this); //error!
    }
}

public interface IConcreteEvent : IBaseEvent<IConcreteEvent>
{ }

public class ConcreteEvent : BaseEvent<IConcreteEvent>, IConcreteEvent
{ }

我收到错误 Cannot convert BaseEvent&lt;T&gt; to T

我试图通过这样做来强制这样做

T value = (T)Convert.ChangeType(this, typeof(T));
return new Message<T>(value);

但我收到错误 Object must implement IConvertible

如果我调试类型,我发现 thisConcreteEvent 类型,而 typeof(T)IConcreteEvent

为什么演员不工作?

【问题讨论】:

  • 您为什么期望您可以将SomeGenericType&lt;T&gt; 转换/转换为T?你能把List&lt;string&gt; 转换成string 吗?
  • @dymanoid 我没有将List&lt;string&gt; 转换为string,我将具体类型ConcreteEvent 转换为它的接口类型IConcreteEvent
  • 不,您将SomeType&lt;T&gt; 转换为T。这是您的代码:(T)this。在这种情况下,thisBaseEvent&lt;T&gt; 的一个实例,您尝试将其转换为 T
  • 我理解错误但我不知道如何解决这个问题
  • 通常你会有一个返回T的成员,这个成员可以用来提供构造函数参数而不是(T)this

标签: c# generics interface casting


【解决方案1】:

终于找到了解决方案,但花了一些时间。

此解决方案不安全:如果类 ConcreteEvent 不实现其接口 IConcreteEvent,您将获得带有消息 Unable to cast object of type 'ConcreteEvent' to type 'IConcreteEvent' 的运行时 InvalidCastException

我还将约束 where T : IBaseEvent&lt;T&gt; 添加到类 BaseEvent&lt;T&gt; 以更好地检查类型。

方法ToMessage可以这样实现

object value = this;
return new Message<T>((T)value);

下面是一个完整的工作示例

void Main()
{
    IConcreteEvent e = new ConcreteEvent();
    Message<IConcreteEvent> msg = e.ToMessage();
}

public class Message<T>
{
    public T Item { get; set; }

    public Message(T item)
    {
        Item = item;
    }
}

public interface IBaseEvent<T>
{
    Message<T> ToMessage();
}

public class BaseEvent<T> : IBaseEvent<T>
    where T : IBaseEvent<T>
{
    public Message<T> ToMessage()
    {
        object value = this;
        return new Message<T>((T)value);
    }
}

public interface IConcreteEvent : IBaseEvent<IConcreteEvent>
{ }

public class ConcreteEvent : BaseEvent<IConcreteEvent>, IConcreteEvent
{ }

【讨论】:

    猜你喜欢
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多