【问题标题】:How to create a List<I> containing instances of B, given instances of A (A derives from B and B implements I)?给定 A 的实例(A 派生自 B,B 实现 I),如何创建包含 B 实例的 List<I>?
【发布时间】:2016-07-27 13:38:48
【问题描述】:

请参阅以下示例代码。

public interface I
{
    int ID { get; set; }
}

public class B : I
{
    public int ID { get; set; }
    public string PropB { get; set; }
}

public class A : B
{
    public string PropA { get; set; }

    public IEnumerable<I> GetListOfBase()
    {
        // Attempt #1
        var list1 = new List<I>();
        B b1 = this as B;
        list1.Add(b1);

        // Attempt #2
        var list2 = new List<I>();
        B b2 = (B)this.MemberwiseClone();
        list2.Add(b2);


        return list1;
    }
}

private static void TestGetListOfBase()
{
    var a = new A() { ID = 1, PropA = "aaa", PropB = "bbb" };
    var list = a.GetListOfBase();
}

在我的两次尝试中,列表都包含 A 的实例。我需要它包含 B 的实例。我试图避免创建新的 B,然后将 A 的属性复制到 B(我认为这会起作用!) .

编辑:我需要一个 B 列表的原因是稍后每个 B 都被传递到 NPoco(一个 .NET 微型 ORM,源自 PetaPoco)。 NPoco 获取类型的名称并使用它来确定要映射到的数据库表。因此,将正确类型的变量传递给方法至关重要。

【问题讨论】:

  • 因为 A 是从 B 派生的,所以 A 的任何实例都是 B 的实例。任何可以使用 B 的地方,也可以使用 A。你能解释一下为什么你需要创建一个 B 列表吗?
  • 这样我就可以将列表传递给 NPoco(一个 .NET 微型 ORM,源自 PetaPoco)。 NPoco 获取类型的名称并使用它来确定要映射到的数据库表。因此,将正确类型的变量传递给方法至关重要。
  • 在这种情况下,您需要将新实例创建为 B 并从 A 的实例中复制值。您不能“伪造”类的类型。在这里使用“复制构造函数”可能会有所帮助。您确定要在持久化数据时省略 A 的所有值吗?

标签: c# inheritance clone derived-class base-class


【解决方案1】:

不,没有办法将派生类的实例“转换”为基类的实例。您必须创建基类的新实例并复制属性。

有多种方法可以做到这一点,包括手动复制每个属性(适用于少量属性)。此操作通常称为“映射”(希望它有助于您搜索工具)。

请注意,如果您对列表 Enumerable.OfType&lt;T&gt;()Enumerable.Cast&lt;T&gt;() 后跟 ToList() 的不同类型感到满意,则可以在单个语句中解决它。

【讨论】:

  • 列表必须是 List,其中 I 是接口。我想我将不得不使用映射技术。
  • @Laurence 您的实际目标是对呼叫者隐藏 A 吗?代理ProxyI 通过转发到实际的A 对象innerA 来实现接口I 的所有方法可能是更好的选择。
  • (错过了对帖子的评论 - 如果需要确切的类型,显然代理是错误的方法)。
【解决方案2】:

您可以使用copy constructor 在给定类型 A 的实例(或任何可分配给 B 的实例)的情况下轻松创建类型 B 的实例:

public class B : I
{
    public int ID { get; set; }
    public string PropB { get; set; }

    public B(source B)
    {
        // copy values
        this.ID = source.ID;
        this.PropB = source.PropB;
    }
}

你可以这样称呼它:

A instanceOfA = new A();
B instanceOfB = new B(instanceOfA);
// typeof(instanceOfB) == B

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    相关资源
    最近更新 更多