将派生类转换为基类可以在使用泛型时保持派生的知识

时间:2014-04-11 18:31:19

标签: c# .net generics inheritance

我有一个奇怪的场景,我似乎无法绕过头脑。我有以下基类:

public class Note
{
    public Guid Id { get; set; }
    public string SenderId { get; set; }
    ...
}

然后由以下类派生:

public class NoteAttachment : Note
{
    public string FileType { get; set; }
    public string MD5 { get; set; }
    ...
}

我使用这些类通过通用包装器与服务器通信:

public class DataRequest<T> : DataRequest
{
    public T Data { get; set; }
}

public class DataRequest
{
    public string SomeField { get; set; }
    public string AnotherField { get; set; }
}

所以我有一个NoteAttachment发送到该方法,但我需要包装一个Note对象发送到服务器。所以我有以下扩展方法:

    public static DataRequest<T> GetDataRequest<T>(this T data)
    {
        DataRequest<T> dataRequest = new DataRequest<T>
        {
            SomeField = "Some Value",
            AnotherField = "AnotherValue",
            Data = data
        };

        return dataRequest;
    }

现在问题。以下列方式调用扩展方法可以正常工作,但即使DataRequest类型为DataRequest<Note>,数据字段的类型为NoteAttachment

var noteAttachment = new NoteAttachment();

...

Note note = (Note)noteAttachment;

var dataRequest = note.GetDataRequest();

Debug.WriteLine(dataRequest.GetType()); //MyProject.DataRequest`1[MyProject.Note]
Debug.WriteLine(dataRequest.Data.GetType()); //MyProject.NoteAttachment <--WHY?!

我做错了什么?

2 个答案:

答案 0 :(得分:4)

你混合了两件事:一个对象的运行时类型和一个字段的编译类型。

Data字段的类型仍为Note。您可以通过反射验证自己。例如,以下内容将打印“注意”:

Console.Write(
     typeof(DataRequest<Note>).GetProperty("Data").PropertyType.Name);

此字段包含的对象的Type可以是Note或任何派生类型。将对象分配给基类的变量不会更改其运行时类。由于GetType()返回对象的类型,因此您获得实际的派生类型(NoteAttachment)。

答案 1 :(得分:3)

当@Alexi回答你的第一个问题时,请在评论中尝试第二个问题。将NotownType属性添加到您的笔记类中,如下所示:

[KnownType(typeof(NoteAttachment)]
public class Note