Reputation: 381
I have the following classes:
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)
{ }
}
I also have a templated method to marshal and instantiate the BiggerHeader
type
public static T Get<T>() where T : HeaderBase
{
HeaderBase b = new HeaderBase(new byte[]{});
T instance = (T)Activator.CreateInstance(typeof(T), b);
return instance;
}
According to MSDN:
where T : <base class name>
: The type argument must be or derive from the specified base class.
However, the value of HeaderSize
is 1 and not 5 as I would have expected. Why would this be the case, and how can I instantiate an object which will use the new
properties from derived types?
Related: Generics in C# - how can I create an instance of a variable type with an argument?
Upvotes: 2
Views: 623
Reputation: 171178
new
members have the same name as a base member but are otherwise unrelated. It looks like you want to make use of virtual
in the base and override
in the derived class.
With new
you essentially silenced the warning that warned you about this. new
had no functional effect.
Calls on T are resolved as if T
was HeaderBase
. Anything else would require the runtime to perform a dynamic binding at runtime based on the name of what you called. Imagine T t; t.Xyz();
. That code would not compile because no Xyz
was found statically. But you are doing the same thing! At the time of compiling the method there is no Derived.HeaderSize
visible because we don't know that T
is going to be Derived
. It could end up being something else. That's why the call is statically bound to Base.HS
. The fact that B.HS
and D.HS
have the same name means nothing. It's a coincidence.
Upvotes: 3
Reputation: 13676
Well, I believe that mainly error here is a result of bad architecture.
Let's add some improvements and make all properties, that has to be changed in every other derived class - abstract
. By doing so we'll make sure that we didn't forget anything, and can start using polymorphism (override behaviour).
Let's also use some features of C# 6.0
It'll also make code more readable :
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)
{
}
}
Upvotes: 1