gpt4 book ai didi

c# - 从基本类型列表中返回正确的后代类型

转载 作者:行者123 更新时间:2023-11-30 16:17:54 26 4
gpt4 key购买 nike

我有一个基类 Foo,它有一个属性,用于从数据库项中识别主键。其他类从我的基类 Foo 派生而来,并包含这些类的特殊性的另一个属性。每个后代类代表数据库中的一个不同表。

通常,当加载这些数据时,这些项目存储在类型为 List 的相同列表中。

当我需要使用某些项目时,我会根据主键找到它。

当这些项目具有相同的主键时,我的问题就出现了,当查看派生类 FooB 中的项目最终找到类 FooA 时,因为这是最先出现的,然后执行转换为 FooB 的地方会引发异常。

var list = new List<Foo>();

list.Add(new FooA() { PrimaryKey = 1 });
list.Add(nwe FooB() { PrimaryKey = 1 });

public Foo FindItem(int pk)
{
return list.First(it => it.PrimaryKey == 1);
}

在很多地方我都是用这种方法来根据自己的需要找到我的元素。

var item = (FooB)FindItem(1);

在其他类中:

var item = (FooA)FindItem(1);

在我的例子中,这段代码在系统中的许多地方使用,将 List 更改为后代项目的列表是一种解决方案,但这意味着在许多地方进行更改,因为我无法传递每个项目的类型我使用的任何地方。

我需要一个不改 rebase 本列表的解决方案。

最佳答案

您需要重写 FindItem(1)方法不返回 Foo 的一个实例而是一个包含 FooA 的特殊对象带有 PrimaryKey==1 的实例和 FooB带有 PrimaryKey==1 的实例.

第二步是提供转换运算符,将这个特殊对象转换为您需要的类型,以便代码 var item = (FooB)FindItem(1)将按预期工作。

下面是实现此类解决方案的完整工作代码。主要缺点是您必须为正在使用的每个派生类型提供转换运算符实现。您也许还可以得出 FooWrapper来自 Foo (在这种情况下,Foo 中只有一个属性会非常简单,但这取决于您实际的 Foo 类)。

using System;
using System.Collections.Generic;
using System.Linq;

namespace FooWrapper
{
class Program
{
private static List<Foo> list = new List<Foo>();

static FooWrapper FindItem(int id)
{
return new FooWrapper(list.Where(o => o.PrimaryKey == id));
}

static void Main(string[] args)
{
list.Add(new FooA() { PrimaryKey = 1, Title = "aaa" });
list.Add(new FooB() { PrimaryKey = 1, Age = 123 });

// test the implicit cast to Foo type. this prefers the FooA type.
Foo item = FindItem(1);
Console.WriteLine(item.PrimaryKey + " - " + item.GetType().Name);

// retrieve the FooWrapper and cast it to FooA type.
var itema = (FooA)FindItem(1);
Console.WriteLine(itema.PrimaryKey + " - " + itema.Title + " - " + itema.GetType().Name);

// retrieve the FooWrapper and cast it to FooB type. The wrapper instance
// retrieved is the same, but the cast retrieves the correct type
var itemb = (FooB)FindItem(1);
Console.WriteLine(itemb.PrimaryKey + " - " + itemb.Age + " - " + itemb.GetType().Name);
}
}

public sealed class FooWrapper
{
private FooA _a;
private FooB _b;

public FooWrapper(IEnumerable<Foo> items)
{
FooA a;
FooB b;
foreach (var i in items)
{
a = i as FooA;
if (a != null)
{
this._a = a;
}
else
{
b = i as FooB;
if (b != null)
this._b = b;
}
}
}

public static implicit operator Foo(FooWrapper obj)
{
if (obj == null)
return null;

return obj._a == null ? (Foo)obj._b : obj._a;
}

public static explicit operator FooA(FooWrapper obj)
{
if (obj == null)
return null;

return obj._a;
}

public static explicit operator FooB(FooWrapper obj)
{
if (obj == null)
return null;

return obj._b;
}
}

public abstract class Foo
{
public int PrimaryKey { get; set; }
}

public class FooA : Foo
{
public string Title { get; set; }
}

public class FooB : Foo
{
public int Age { get; set; }
}
}

关于c# - 从基本类型列表中返回正确的后代类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16691804/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com