提问人:Tirais 提问时间:5/30/2023 最后编辑:Tirais 更新时间:5/31/2023 访问量:89
如何在没有“dynamic”关键字的情况下在 C# 中动态定义方法的返回类?
How can I define a method's return class dynamically in C# without the 'dynamic' keyword?
问:
我有几个从“可脚本对象”Unity继承的类 - “Item”是主类,其他类是从中继承的:“Tool”、“Weapon”、“Food”和其他几个类。我只能通过字典访问类的每个实例(例如:我可以通过其名称(字符串)获取所需的项目,并且由于所有字典的键数据类型相同,因此我无法进行方法重载。因此,在运行时,必须定义类并且它必须返回,但我不知道如何在没有动态类型的情况下做到这一点。
我认为可以通过元组同时返回多个类实例,但是您必须为每个方法调用创建一个额外的检查,当代码增长时,这将导致代码支持困难。据我所知,动态类型如果您经常使用它,可能会导致性能下降。Dictionary <string, Tool> toolsDatabase; Dictionary <string, Weapon> weaponsDatabase; Dictionary <string, Food> foodsDatabase");
这里有一些代码。也许我真的没有为 C# 提出正确的问题。简而言之,任务是使用一个关键字和一个方法从多个字典中获取不同的类,这些字典将不同的类存储在值中。 private static Dictionary<string, Item> items;
public static Dictionary<string, Item> Items => items;
private static Dictionary<string, Tool> tools;
public static Dictionary<string, Tool> Tools => tools;
private static Dictionary<string, Weapon> weapons;
public static Dictionary<string, Weapon> Weapons => weapons;
[SerializeField] private List<Item> itemsDatabase = new List<Item>();
[SerializeField] private List<Tool> toolsDatabase = new List<Tool>();
[SerializeField] private List<Weapon> weaponsDatabase = new List<Weapon>();
public Item GetItem(string itemName)
{
foreach (var item in items)
{
if (item.Key == itemName)
{
return item.Value;
}
}
foreach (var tool in tools)
{
if (tool.Key == itemName)
{
return tool.Value;
}
}
foreach (var weapon in weapons)
{
if (weapon.Key == itemName)
{
return weapon.Value;
}
}
return new Item();
}
答:
我会使用一本字典
Dictionary<string, Item> itemsDatabase;
然后,您可以选择查找具有给定键的任何类型的项,或者您可以将此方法与泛型类型参数一起使用:
private bool TryGetItem<T>(string key, out T t)
where T : Item
{
if (itemsDatabase.TryGetValue(key, out Item item) && item is T specificItem) {
t = specificItem;
return true;
}
t = null;
return false;
}
用法
if (TryGetItem<Food>("apple", out Food apple)) {
// ...
}
这可以通过仅指定参数的类型或仅指定泛型类型参数并让 C# 编译器推断另一个参数来简化:out
if (TryGetItem("apple", out Food apple)) {
}
// OR
if (TryGetItem<Food>("apple", out var apple)) {
}
或者您可以像这样打开类型
if (itemsDatabase.TryGetValue("someKey", out Item item)) {
switch (item) {
case Tool tool:
tool.Apply();
break;
case Weapon weapon:
weapon.Attack();
break;
case Food food:
food.Eat();
break;
}
}
在某些情况下,还可以使用多态性来避免型式试验。示例:不要像 一样为每个项目类型使用不同的方法,如 ,如上所示,而是在抽象基类中添加一个抽象方法。然后,每种类型的项都会添加自己的实现。Apply
Attack
Eat
Use
Item
if (itemsDatabase.TryGetValue("someKey", out Item item)) {
item.Use(); // Tools are applied, weapons attack and food is eaten.
}
评论
TryGetItem
评论
Tool GetTool(string name)
TItem Get<TItem>(string key) where TItem: Item
dynamic
GetTool