【问题标题】:Calling child variables from another generic class which generic is parent从另一个泛型类调用子变量,泛型是父类
【发布时间】:2020-04-10 07:44:50
【问题描述】:

我正在使用 c# 语言进行统一。

库存系统需要使用父子类。

我的脚本概念如下。

而且我总是在我标记它时出错。

我知道虚拟覆盖可以解决这个问题,但我只是想知道

可以用这个概念吗?

public class A
{
    public int a;
}

public class B : A
{
    public int b;
}

public class C : A
{
    public int c;
}


public class Main<T> where T : A, new()
{
    public void callValue(T item)
    {
        if (item is B)
        {
            Console.WriteLine(item.a + "||" + ((B)item).b); // error cannot convert T to B;
        }
        if (item is C)
        {
            Console.WriteLine(item.a + "||" + ((C)item).c);
        }
    }
}

【问题讨论】:

标签: c# generics inheritance


【解决方案1】:

您的代码非常接近。您可以使用if (item is X x_item),然后使用x_item 作为X 类型。像这样:

public class Main<T> where T : A, new()
{
    public void callValue(T item)
    {
        if (item is B b_item)
        {
            Console.WriteLine(item.a + "||" + b_item.b);
        }
        if (item is C c_item)
        {
            Console.WriteLine(item.a + "||" + c_item.c);
        }
    }
}

但是有这样的通用方法似乎很奇怪。

例如,我可以这样做:

public class D : A
{
    public int d;
}

然后是这个:

    var m = new Main<D>();
    m.callValue(new D());

如果是这样,那么尝试转换为 BC 有什么意义?

你的设计很糟糕。

【讨论】:

  • 这段代码非常适合我谢谢。我正在尝试建立多个库存来存储设备、可用、材料和其他。所以每个库存需要检查项目类型,项目类型可以堆叠与否。因为如果不需要堆叠项目,只需找到空槽并添加它。但如果没有,请检查每个插槽的项目并添加数量。这就是为什么我需要单独的方法来依赖于项目类型我会写更详细的代码来回答你
  • @Natejin - 您使用继承的方式会让您陷入困境。使用IStackable 接口可能是更好的选择。
【解决方案2】:

这是我的使用代码;

public class ItemType
{
    public int ID;
}

public class UnstackableItem : ItemType
{

}

public class Equipment : UnstackableItem {
    public int durability;
}

public class StackableItem : ItemType
{
    public int amount;
}

public class Useable : StackableItem { 

}

public class Material : StackableItem { 

}
public class D : ItemType
{
    public int d;
}

public class Main<T> where T : ItemType, new()
{
    List<T> items;
    Dictionary<int, int> stackCheck;

    public void AddItem(T item, int amount)
    {
        if (item is StackableItem)
        {
            StackableItem(item, amount);
        }
        if (item is UnstackableItem)
        {
            UnStackableItem(item);
        }
    }

    public void UnStackableItem(T item) {
        if (item is StackableItem)
        {
            items.Add(item);
        }

    }

    public void StackableItem(T item, int amount)
    {
        if (stackCheck.ContainsKey(item.ID))
        {
            var itemFrominventory = items[stackCheck[item.ID]];

            if (itemFrominventory is StackableItem unstackItem)
            {
                unstackItem.amount += amount;
            }
        }
        else
        {
            //find empty Slot return value is emptySlotID
            items.Add(item);
            stackCheck.Add(item.ID, emptySlotID);
        }
    }
}

【讨论】:

  • 我在回答中提出的问题不是很清楚。我真的想问为什么class Main&lt;T&gt; where T : ItemType, new()class Main { public void AddItem(ItemType item, int amount) {} } 就足够了。将Main 设为通用有什么意义?
  • @Enigmativity - 因为我需要通过 BinaryFormatter 保存库存数据。因此,必须对数据进行序列化。如果我只使用 Main 类,并保存它。我将失去装备类中的耐用性变量或可堆叠物品中的数量。所以我需要制作 Main(或 Inventory)来制作每种类型的库存并保存它。所以我可以加载我所有的数据。如果您有其他想法或想查看我的代码,请告诉我。
  • 不,我不认为你这样做。从内存中,BinaryFormatter 将保存对象的具体类型,而不管您引用的运行时类型如何。
  • 哦 json 不是保存类型,但 binaryFormatter 可以在不使用通用的情况下工作 谢谢 man ^^
  • 什么? “哦 json 不是保存类型,但 binaryFormatter 可以在不使用泛型的情况下工作”
【解决方案3】:

更新这些行以使用 as 而不是显式转换:

Console.WriteLine(item.a + "||" + (item as B).b);

Console.WriteLine(item.a + "||" + (item as C).c);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-19
    • 2014-08-02
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2018-06-12
    相关资源
    最近更新 更多