I have two parent classes: Item and ItemData. From the first, I make items such as WeaponItem and from the second I make corresponding data like WeaponData.
Each item type takes the same type of data in its constructor (example: when creating WeaponItem it needs WeaponData).

我有以下方法:

public static T CreateNewItem<T, DT>(ItemData data) where T : Item where DT : ItemData
{
    if (data == null) return null;
    if (data is DT dt)
    {
        //determine type of T
        Type itemType = typeof(T);
        if (itemType = typeof(WeaponItem))
        {
                //make a new weapon item...
                WeaponItem new_weapon = new WeaponItem(dt); //error!
                return new_weapon;
        }
        if (itemType = typeof(ArmorItem))
        {
                //make a new armor item...
        }
        //etc...
    }
    return null;
}

我这样称呼它:

CreateNewItem<WeaponItem, WeaponData>(data);

注:dataItemData型或某些继承型(如WeaponData).

这种方法需要两种类型:一种用于Item,另一种用于ItemData.我有几件物品(武器、盔甲等)我根据我给出的类型创建项目.我还想判断我使用的数据:data is DT dt从我通过的数据中获得WeaponData,或者null如果转换失败.

当我try 做WeaponItem new_weapon = new WeaponItem(dt);次时,我得到以下错误:

参数1:无法从'DT'转换为'WeaponData'[Assembly CSharp]CSharp(CS1503)

我试着把dt投到WeaponData,就像这样:WeaponItem new_weapon = new WeaponItem((WeaponData)dt);,但我得到了一个类似的错误

无法将类型"DT"转换为"WeaponData"[Assembly CSharp]CSharp(CS0030)

类似地,使用data代替dt会产生错误.


不必每次判断型号就可以解决这个问题吗?

推荐答案

你的设计对我来说有点违反直觉,所以让我们从一个非常简单的通用方法开始,并从那里开始.这段代码可以复制和编译.

你也可以点击this link然后点击Run按钮.

我想说,这里最大的优势是通用方法变成了一行代码.您可以添加任意数量的项目,并且永远不会更改该方法.然而,您的实现变得越来越复杂.

代码:

public class ItemData
{
    public string ItemName { get; init; }
}

public class WeaponData : ItemData { }

public class Item
{
    public ItemData Data { get; init; }

    public Item(ItemData data)
    {
        Data = data;
    }
}

public class WeaponItem : Item  
{
    public WeaponItem(WeaponData data) : base(data) { }

    public override string ToString() => Data.ItemName;
}

public static T CreateNewItem<T, TD>(TD data) 
    where T : Item 
    where TD : ItemData
{
    return (T)Activator.CreateInstance(typeof(T), data);
}

static void Main(string[] args)
{
    var bestWeaponDataEver = new WeaponData() { ItemName = "屠龙者" };
    var amazingWeapon = CreateNewItem<WeaponItem, WeaponData>(bestWeaponDataEver);
    Console.WriteLine(amazingWeapon);
}

输出:

屠龙者

另一个很大的区别是您接受的是特定类型ItemData,它应该是泛型类型DT.否则为什么DT会存在?这可能把你绊倒了.

public static T CreateNewItem<T, DT>(ItemData data) where T : Item where DT : ItemData

应该是这个吗

public static T CreateNewItem<T, DT>(DT data) where T : Item where DT : ItemData

注意WeaponItem的构造函数只接受WeaponData.所以,尽管有简单的通用方法,你不能用ItemDataCakeData或其他任何东西制造武器.

如果你不确定如何扩展这条 comments ,我将try 进一步提供帮助.

Csharp相关问答推荐

将json作为字符串发送到API会导致错误,但发送dotnet对象不会

将序列化的IasyncESYS上传到Azure Blob存储的最佳方法是什么

在Microsoft XNA框架(MonoGame)中旋转相机

使用C#中的Shape API从Azure目录获取所有用户

react 式扩展连接中的非交叉LeftDurationTimeout

如何使用C#和Graph API从Azure Directory获取用户详细信息

属性getter和setter之间的空性不匹配?

如果属性名为xyz,我需要使用System.Text.Json修改字符串类型的值""<>

如何使用C#Interop EXCEL创建度量衡

从.Net 6 DLL注册和检索COM对象(Typelib导出:类型库未注册.(异常来自HRESULT:0x80131165))

由于POST中的应用程序/JWT,出现不支持的内容类型异常

在DoubleClick上交换DataGridViewImageColumn的图像和工具提示

如何允许数组接受多个类型?

我找不到ASP.NET Web应用程序(.NET框架).已 Select .NET框架项目和项模板以及此组件(&Q;)

C#LINQ延迟执行和嵌套方法

Blazor:搜索框在第一次搜索时不搜索

如何在使用属性 Select 器时判断是否可以为空

基于C#方法的EF核心过滤查询(缓冲与流)

如何在一次数据库调用中为ASP.NET核心身份用户加载角色

毛伊岛.NET 8图片不再适合按钮