派生类型

时间:2016-08-03 13:36:55

标签: c# .net-3.5

我有以下课程:

public class HeaderBase
{
    public int HeaderSize { get { return sizeof(byte); } }
    public byte[] Content { get; private set; }

    public HeaderBase(byte[] bytes)
    {
        Content = bytes;
    }
}

public class BiggerHeader : HeaderBase
{
    public new int HeaderSize { get { return sizeof(byte) + sizeof(UInt32); } }

    public BiggerHeader(HeaderBase header) : base(header.Content)
    { }     
}

我还有一个模板化方法来编组和实例化BiggerHeader类型

public static T Get<T>() where T : HeaderBase
{
    HeaderBase b = new HeaderBase(new byte[]{});
    T instance = (T)Activator.CreateInstance(typeof(T), b);
    return instance;
}

根据MSDN

  

where T : <base class name>:类型参数必须是或从指定的基类派生

但是,HeaderSize的值是1,而不是我预期的5。为什么会出现这种情况,如何实例化一个将使用派生类型的new属性的对象?

DotNetFiddle

相关:Generics in C# - how can I create an instance of a variable type with an argument?

2 个答案:

答案 0 :(得分:3)

new成员与基本成员具有相同的名称,但在其他方面不相关。看起来您希望在基础中使用virtual,在派生类中使用override

使用new你基本上会使警告无声,警告你这件事。 new没有任何功能效果。

对T的调用已解决,就像THeaderBase一样。其他任何事情都需要运行时根据您调用的名称在运行时执行动态绑定。想象一下T t; t.Xyz();。该代码无法编译,因为静态未找到Xyz。但你做的是同样的事情!在编译方法时,没有Derived.HeaderSize可见,因为我们不知道T将是Derived。它可能最终成为别的东西。这就是呼叫静态绑定到Base.HS的原因。 B.HSD.HS具有相同名称的事实毫无意义。这是巧合。

答案 1 :(得分:1)

嗯,我相信这里的错误主要是糟糕的架构造成的。

让我们添加一些改进并创建所有属性,这些属性必须在每个其他派生类中更改 - abstract。通过这样做,我们将确保我们不会忘记任何事情,并且可以开始使用多态(覆盖行为)。

让我们也使用C#6.0的一些功能

它还会使代码更具可读性:

public abstract class AbstractHeader
{
    public abstract int HeaderSize { get; }
    public virtual byte[] Content { get; set; }

    protected AbstractHeader() { }

    protected AbstractHeader(byte[] bytes)
    {
        Content = bytes;
    }
}

public class BaseHeader : AbstractHeader
{
    public override int HeaderSize => sizeof (byte);
}

public class BiggerHeader : AbstractHeader
{
    public override int HeaderSize => sizeof (byte) + sizeof (UInt32);

    public BiggerHeader(BaseHeader header) : base(header.Content)
    {
    }
}