将派生类的实体传递给泛型方法

时间:2018-06-06 08:36:38

标签: c# generics inheritance

我有四个类,如:

class BaseA { }

public class DerivedA : BaseA { }

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

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

用于以下程序:

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
}

如果我传入SomeMethod DerivedB类型的参数,则param有2个属性SomeProperty - 基类和派生类类型。但无论param是什么类型,它都被视为BaseB类,我必须明确地将其转换为必需的类型以获得正确的SomeProperty值。施放到T没有帮助。 我应该将param变量强制转换为自己的类型,还是至少可以获得一个非空值的属性?

3 个答案:

答案 0 :(得分:0)

  

但无论param是什么类型,它都被视为BaseB类,我必须将其显式地转换为必需的类型才能获得正确的SomeProperty值。

是。因为该绑定是在编译时执行的,所以编译器只知道BaseB.SomeProperty。这是将在IL中引用的属性,以及将在执行时获取的属性。

我认为拥有两个具有相同名称的独立属性实在令人困惑。如果确实想要这样做,您可以强制在执行时进行绑定,而不是使用动态类型:

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;
}

但是如果可能的话,我会完全避免这种设计。要么具有单独命名的属性,所以它们显然是独立的,或者具有单个状态的属性,可以根据实例的“视图”以不同方式访问(如果您有异常风险)将属性设置为“错误”类型。)

答案 1 :(得分:0)

您需要的是将通用转换为class而不是BaseB 并且参数类型为动态。这将处理引用运行时。

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

此外,我不认为这里是否真的需要遮蔽。

此外,您可以删除通用类型。它仍将适用于您的情况

只是

static void SomeMethod<T>(T param)

答案 2 :(得分:0)

隐藏基本属性可能不是最好的方法。

使用您的小样本,基类和派生类是空的,因此找出您需要的内容有点棘手。

有两种更清洁,更简单的方法:

  • 考虑创建一个接口,基类,派生类和泛型类型(在SomeMethod中使用)都将实现...然后它很容易

  • 如果您的需求无法使用通用接口,请考虑将基类创建为通用类

希望这有帮助