0

I have four classes like:

class BaseA { }

public class DerivedA : BaseA { }

public class BaseB
{
    public BaseA SomeProperty { get; set; }
}

public class DerivedB : BaseB
{
    public new DerivedA SomeProperty { get; set; }
}

which are used in program like:

static void Main(string[] args)
{
    var derivedB = new DerivedB();
    derivedB.SomeProperty = new DerivedA();

    SomeMethod(derivedB);
}

static void SomeMethod<T>(T param) where T : BaseB
{
    var tmp1 = param.SomeProperty;               // null
    var tmp2 = (param as DerivedB).SomeProperty; // required value
    var tmp3 = (param as T).SomeProperty;        // null
}

If I pass in SomeMethod a parameter of type DerivedB, param has 2 properties SomeProperty - of base and derived class types. But no matter of what type is param, it is treated as BaseB class and I have to explicitly cast it to required type to get the right SomeProperty value. Casting to T does not help. Should I cast the param variable to its own type or can I get at least a property with not-null value?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
AlexK
  • 561
  • 7
  • 22
  • 3
    The fact that you shadow the baseB property in derivedB is what's causing all these problems. Why not make baseB's property generic as well? – Zohar Peled Jun 06 '18 at 08:41
  • Possible duplicate of ["new" keyword in property declaration in c#](https://stackoverflow.com/questions/3649174/new-keyword-in-property-declaration-in-c-sharp) – CodeNotFound Jun 06 '18 at 08:41

3 Answers3

0

But no matter of what type is param, it is treated as BaseB class and I have to explicitly cast it to required type to get the right SomeProperty value.

Yes. Because that binding is performed at compile-time, at which point the compiler only knows about BaseB.SomeProperty. That's the property that will be referenced in the IL, and the property that will be fetched at execution time.

I'd argue that having two independent properties with the same name is really confusing. If you really want to do this, you could force the binding to occur at execution time instead using dynamic typing:

static void SomeMethod<T>(T param) where T : BaseB
{
    dynamic d = param;
    // This will use the execution-time type of param
    var tmp1 = d.SomeProperty;
}

But I'd avoid this design entirely if you possibly can. Either have separately named properties so they're obviously independent, or a property with a single piece of state which can be accessed differently based on the "view" of the instance (with the risk of exceptions if you set the property to the "wrong" type).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

What you need is to convert your generic to type class instead of BaseB and the parameter types to dynamic. This will handle references run time.

static void SomeMethod<T>(T param) where T : class
        {
            dynamic tmp1 = param; 
            var myProperty = tmp1.SomeProperty;
        }

Also, I don't think if shadowing is really necessary here.

Additionally, You can remove type for generic. It will still work in your case

Just

static void SomeMethod<T>(T param)
Manoz
  • 6,507
  • 13
  • 68
  • 114
0

Shadowing the base property is probably not the best way to go.

With your tiny sample, base and derived classes are empty, so it is a bit tricky to figure out what you need exactly.

Two cleaner and easier ways comes in mind :

  • consider creating an interface that base class, derived class and generic type (used in SomeMethod) will all implement ... and then it is fairly easy

  • if the common interface is not possible for your needs, consider creating base class as a generic class

Hope this helps

Seb T.
  • 1,104
  • 12
  • 27