派生类型中的“Activator.CreateInstance”和“新”属性
`Activator.CreateInstance` and `new` properties in derived types
我有以下 类:
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>
: The type argument must be or derive from the specified base class.
然而,HeaderSize
的值是 1,而不是我预期的 5。为什么会这样,我如何实例化一个将使用派生类型的 new
属性的对象?
相关:Generics in C# - how can I create an instance of a variable type with an argument?
new
成员与基本成员同名,但在其他方面不相关。看起来您想在基础中使用 virtual
并在派生的 class.
中使用 override
使用 new
您基本上消除了警告您的警告。 new
没有任何功能性影响。
对 T 的调用被解析为就好像 T
是 HeaderBase
。其他任何事情都需要运行时根据您调用的名称在运行时执行动态绑定。想象一下 T t; t.Xyz();
。该代码无法编译,因为未静态找到 Xyz
。但是你在做同样的事情!在编译该方法时,没有 Derived.HeaderSize
可见,因为我们不知道 T
将成为 Derived
。它最终可能会变成别的东西。这就是调用静态绑定到 Base.HS
的原因。 B.HS
和 D.HS
同名这一事实没有任何意义。真是巧合。
好吧,我认为这里的错误主要是由于糟糕的体系结构造成的。
让我们添加一些改进并制作所有属性,这些属性必须在每个其他派生的 class - 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)
{
}
}
我有以下 类:
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>
: The type argument must be or derive from the specified base class.
然而,HeaderSize
的值是 1,而不是我预期的 5。为什么会这样,我如何实例化一个将使用派生类型的 new
属性的对象?
相关:Generics in C# - how can I create an instance of a variable type with an argument?
new
成员与基本成员同名,但在其他方面不相关。看起来您想在基础中使用 virtual
并在派生的 class.
override
使用 new
您基本上消除了警告您的警告。 new
没有任何功能性影响。
对 T 的调用被解析为就好像 T
是 HeaderBase
。其他任何事情都需要运行时根据您调用的名称在运行时执行动态绑定。想象一下 T t; t.Xyz();
。该代码无法编译,因为未静态找到 Xyz
。但是你在做同样的事情!在编译该方法时,没有 Derived.HeaderSize
可见,因为我们不知道 T
将成为 Derived
。它最终可能会变成别的东西。这就是调用静态绑定到 Base.HS
的原因。 B.HS
和 D.HS
同名这一事实没有任何意义。真是巧合。
好吧,我认为这里的错误主要是由于糟糕的体系结构造成的。
让我们添加一些改进并制作所有属性,这些属性必须在每个其他派生的 class - 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)
{
}
}