【问题标题】:Try cast to a child type and if it doesn't work cast to a different child type c#尝试转换为子类型,如果它不起作用,则转换为不同的子类型 c#
【发布时间】:2018-02-14 19:08:33
【问题描述】:

我正在尝试创建一个函数,该函数可以接收实际上是 Child1、Child2 或 Child3 类型的 Parent 类的参数。我想根据它是哪种孩子类型做一些不同的事情,除了我在下面显示的内容之外,我想不出其他方法。这对我来说是错误的,所以任何关于更好方法的建议都将不胜感激。

public static bool DoStuff(Parent parent)
{
    try
    {
        Child1 child = parent as Child1;
        DoStuffChild1(child);
    }
    catch (Exception)
    {
        try
        {
            Child2 child = parent as Child2;
            DoStuffChild2(child);
        }
        catch(Exception)
        {
            try
            {
                Child3 child = parent as Child3;
                DoStuffChild3(child);
            }
            catch (Exception)
            {
                HandleError();
            }
        }
    }
}

【问题讨论】:

  • 可以选择 C# 7 吗?模式匹配功能肯定是比这更好的解决方案。
  • 即使排除这些,为什么还需要异常处理?如果演员表失败,那么孩子应该是null
  • 你完全正确,这是错误的。我不仅会在代码审查中拒绝这一点,我还会带你回去向你开枪;)查找 typeof.GetType() - 如果你愿意,我会写一个涵盖这些选项的答案。
  • 是的,就像@EvanTrimboli 所说的那样,这不会像您期望的那样工作,因为转换失败只会导致分配 null 而不是异常。
  • 我知道这会起作用,因为 Visual Studio 需要一个 try-catch 围绕此处的“as”强制转换,以防它无法将其强制转换为子类。然而,这太恶心了,我永远无法提交任何形式的审查。 @EvilGeniusJamie 我几乎想把自己带回来,让我想到这一点。感谢所有的答案。

标签: c# inheritance


【解决方案1】:

您可以简单地使用 is 关键字代替:

public static bool DoStuff(Parent parent)
{
            try
            {
                if (parent is Child1)
                {
                    Child1 child = parent;
                    DoStuffChild1(child);
                }
                else if (parent is Child2)
                {
                    Child2 child = parent;
                    DoStuffChild2(child);
                }
                else if (parent is Child3)
                {
                    Child3 child = parent;
                    DoStuffChild3(child);
                }
            }
            catch (Exception)
            {
                HandleError();
            }
}

is 如果实例在继承树中,则返回 true。

此外,以下是关于类型检查的一个很好的答案: https://stackoverflow.com/a/983061/4222487

【讨论】:

  • 您甚至可以在后面添加一个变量名来自动创建变量。 if (parent is Child1 child1) { DoStuffChild1(child1); }
  • @BlakeThingstad 我相信从 C#7 开始就是这样?
  • 或者如果你不在 C#7 上,你可以这样做:if (parent is Child1) { DoStuffChild1((Child1) parent); }
  • @EvilGeniusJamie 是的,据我了解,它是模式匹配的一部分。在Pattern Matching documentation 中进行了一些讨论
  • 谢谢。我正在处理的唯一错误是它不是任何可能的类型。我应该澄清一点。这就是我一直在寻找的。​​span>
【解决方案2】:

如果您使用的是 C# 7.0 或更高版本,您可以使用以下代码实现您想要的:

if (parent is Child1 child1)
{
    DoStuffChild1(child1);
}
else if (parent is Child2 child2)
{
    DoStuffChild2(child2);
}

希望这会有所帮助。

【讨论】:

  • 太棒了。正是我想要的。
【解决方案3】:

如果 C# 7 不是一个选项,此方法将适用于旧版本的 C#。


不要使用try/catch 作为控制流。永远。

如果你需要根据对象的类做不同的事情,你可以使用typeof.GetType()。在你的例子中

public static bool DoStuff(Parent parent)
{
    if (parent.GetType() == typeof(Child1))
    {
        Child1 child = parent as Child1;
        DoStuffChild1(child);
    }
    else if (parent.GetType() == typeof(Child2))
    {
        Child2 child = parent as Child2;
        DoStuffChild2(child);
    }
    else if (parent.GetType() == typeof(Child3))
    {
        Child3 child = parent as Child3;
        DoStuffChild3(child);
    }
    else
    {
        HandleError();
    }
}

是一种简单的处理方式。


在 FaizanRabbani 的回答中,您在 is 关键字上使用它的原因是此方法是严格的类型检查,忽略超类 - 例如:

if (parent is Parent)

会评估true,但是

if (parent.GetType() == typeof(Parent))

将评估false,例如,如果它是Child1Child2Child3

【讨论】:

  • 注意:@rufus-l 对这个问题的评论是我完全尝试/赶上的原因
  • 谢谢。我确实有可用的 C# 7。
  • 投反对票的人是否愿意解释这个答案有什么问题...?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2010-12-17
  • 1970-01-01
相关资源
最近更新 更多