c# 返回 upcasted 实例作为它的原始类型 使用泛型在调用方投射到目标类型调用方的类型检查

如何解决c# 返回 upcasted 实例作为它的原始类型 使用泛型在调用方投射到目标类型调用方的类型检查

我正在尝试将向上转换的实例作为原始类型返回。

public class Card : MonoBehavIoUr
{
    [Serializefield]
    private CardInfo cardInfo;
    public CardInfo Info { get => cardInfo; }
}

public abstract class CardConsumable : Card
{
}
    

public class CardDataBase : MonoSingleon<CardDataBase>
{
    //list will contain derived class of cards as element
    private List<Card> allCards = new List<Card>(100);
 
    public dynamic GetCard(int id)
    {
        int count = allCards.Count;
        for (int i = 0; i < count;i++)
            if(allCards[i].Info.Id == id)
            {
                var card = allCards[i];
                //tried this but got error
                //var cardType = card.GetType();
                //card = card as cardType;
            }
        return null;          
    }
}

例如,在 GetCard() 中,如果 id 与参数相同且其原始类型为 CardConsumable 的元素,那么我想将其作为 CardConsumable 返回 不是卡片。简而言之,我想返回实例,因为它是原始类型而不是向上转换类型

解决方法

使用泛型

除了 this answer 之外,您还可以使用 generic method 并提供您正在寻找的所需类型,并且只使用 Linq OfType 返回该类型的实例,例如

// T will be whatever type you pass in
// "where T : Card" makes sure only types derived from "Card" can be used 
public T GetCard<T>(int id) where T : Card
{
   return  allCards.OfType<T>().SingleOrDefault(x => x.Info.Id == id);
}

当然这不是完全“动态的”,因为您需要已经知道您正在寻找的类型;)

你会这样称呼它

CardConsumable cardConsumable = cardDatabase.GetCard<CardConsumable>(id);

如果没有找到类型为 nullCardConsumable 的卡片,它将返回 id

或者例如

Card card = cardDatabase.GetCard<Card>(id);

只需要匹配 id,但可以返回任何派生自 Card 的类型。


在调用方投射到目标类型

如果你真的想要动态运行时,你可以做同样的事情,但就像

public Card GetCard<(int id,Type type)
{
   return allCards.SingleOrDefault(x => (x.GetType().IsSubclassOf(type) || x.GetType() == type) && x.Info.Id == id);
}

在这里你需要再次投射

var possiblyDynamicType = typeof (CardConsumable);
CardConsumable cardConsumable = (CardConsumable) cardDatabase.GetCard(id,typeof(possiblyDynamicType));

调用方的类型检查

或者说你每次拿到类似的卡片时都需要进行类型检查

public Card GetCard(int id) => allCards.SingleOrDefault(x => x.Info.Id == id);

然后做例如

var card = cardConsumable = cardDatabase.GetCard(id);

switch(card)
{
    case CardConsumable cardConsumable:
        // Do CardConsumable specific stuff
        cardConsumable.Consume();
        break;

    case SomeOtherCardType someOtherCard:
        // Do SomeOtherCardType specific stuff
        someOtherCard.SomeThing();
        break;

    default:
        // do default stuff for the rest of Card types
        break;
}
,

GetCard 方法可以返回“Card”(非动态)。

然后您可以对结果使用 GetType() 或 IsAssignableFrom() 以获取派生类型并根据需要进行转换。

https://docs.microsoft.com/en-us/dotnet/api/system.type.isassignablefrom?view=net-5.0

,

由于数据库中存储的所有卡片都是Card类型,因此您可以将GetCard方法编写为

public Card GetCard(int id) => allCards.SingleOrDefault(x => x.Info.Id == id);

然后在返回的卡片上调用 GetType() 以获取具体类型。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?