C# 多态性与显式投射

C# 多态性与显式投射,c#,casting,polymorphism,C#,Casting,Polymorphism,我有以下体系结构(这个类比很糟糕,但是W/E) 在program和其他逻辑类中,我有很多方法使用特定类型的手指(MonkeyFinger)。这意味着我必须显式地强制转换所有这些测试方法 是否有任何设计模式/解决方案可以避免显式强制转换 编辑代码: Monkey govi = new Monkey(...) Program test = new Program() test.testFinger1((MonkeyFinger) govi.GetHand.getFinger) …我认为最好创建一

我有以下体系结构(这个类比很糟糕,但是W/E)

program
和其他逻辑类中,我有很多方法使用特定类型的手指(
MonkeyFinger
)。这意味着我必须显式地强制转换所有这些测试方法

是否有任何设计模式/解决方案可以避免显式强制转换

编辑代码:

Monkey govi = new Monkey(...)
Program test = new Program()
test.testFinger1((MonkeyFinger) govi.GetHand.getFinger)

我认为最好创建一个方法来为您执行检查。是的,如果你想测试一些假设(比如一只猴子只有猴子的手指),那么这个角色是必要的

比如:

public static T TestAndConvert<T>(object o)
{
    Assert.IsInstanceOfType(o, typeof(T));

    return (T)o;
}
公共静态T测试和转换(对象o)
{
IsInstanceOfType(o,typeof(T));
返回(T)o;
}
这里首先检查类型是否正确,然后返回一个类型化实例。通过这种方式,您可以确保类型正确,并且进行了适当的测试

在测试调用中使用它:

testFinger1(TestAndConvert<MonkeyFinger>(finger));
testFinger1(TestAndConvert(finger));

(从您的图表中,我不确定您是否使用自动化测试框架,如Visual Studio中的单元测试,我建议您这样做)

我认为最好创建一个方法来为您执行检查。是的,如果你想测试一些假设(比如一只猴子只有猴子的手指),那么这个角色是必要的

比如:

public static T TestAndConvert<T>(object o)
{
    Assert.IsInstanceOfType(o, typeof(T));

    return (T)o;
}
公共静态T测试和转换(对象o)
{
IsInstanceOfType(o,typeof(T));
返回(T)o;
}
这里首先检查类型是否正确,然后返回一个类型化实例。通过这种方式,您可以确保类型正确,并且进行了适当的测试

在测试调用中使用它:

testFinger1(TestAndConvert<MonkeyFinger>(finger));
testFinger1(TestAndConvert(finger));

(从您的图表中,我不确定您是否使用了自动化测试框架,如Visual Studio中的单元测试,我建议您这样做)

是否真的需要将具体的手指传递给测试方法?当您使用接口时,您需要定义一个契约,每个实现都应该遵循该契约。您可以使用方法重写来扩展子类中的父行为(或替换它,但它不对应),但您只测试契约,那么为什么您需要在测试方法中传递MonkeyFinger而不是IFinger?

是否真的需要传递具体的finger到测试方法?当您使用接口时,您需要定义一个契约,每个实现都应该遵循该契约。您可以使用方法重写扩展子类中的父行为(或替换它,但它不对应),但您只测试契约,那么为什么您需要在测试方法中通过MonkeyFinger而不是IFinger?

您可以尝试以下方法:

public class Animal<TFingerType> where TFingerType : IFinger
{
    Hand<TFingerType> GetHand() 
    {
        //... Do something
    }
}

public class Monkey : Animal<MonkeyFinger> { }
public class Hand<TFingerType> where TFingerType : IFinger
{

}
public interface IFinger
{

}
public class MonkeyFinger : IFinger {
}

请注意,手指仍然是
iFinger
,可以在该上下文中使用,但这种方法也提供了具体键入的手指。

您可以尝试以下方法:

public class Animal<TFingerType> where TFingerType : IFinger
{
    Hand<TFingerType> GetHand() 
    {
        //... Do something
    }
}

public class Monkey : Animal<MonkeyFinger> { }
public class Hand<TFingerType> where TFingerType : IFinger
{

}
public interface IFinger
{

}
public class MonkeyFinger : IFinger {
}


请注意,手指仍然是
IFingers
,可以在该上下文中使用,但这种方法也提供了具体类型的手指。

可以显示代码吗?动物一只手只有一个手指?@YacoubMassad实际代码非常复杂,我添加了一些伪代码。@WillemVanOnsem我知道它应该是某种类型的列表,但是不要担心类比。有没有理由需要将
getFinger
的返回值强制转换为
MonkeyFinger
?在
MonkeyFinger
的公共界面中有什么特殊的东西没有在
IFinger
中定义吗?你能显示代码吗?动物一只手只有一个手指吗?@YacoubMassad实际的代码非常复杂,我添加了一些伪代码。@WillemVanOnsem我知道它应该是某种类型的列表,但是不要担心类比。有没有理由需要将
getFinger
的返回值强制转换为
MonkeyFinger
?在
MonkeyFinger
的公共界面中是否有一些特殊的东西没有在
IFinger
中定义?不确定这个断言提供了什么好处。Cast操作符将通过抛出异常让您知道Cast是否有效。它将在您的测试概述中提供更好的指示器。异常通常会告诉您测试中存在代码错误。断言将向您显示您已经想到了它,并且您可以预期它会出错。不确定此断言提供了什么好处。Cast操作符将通过抛出异常让您知道Cast是否有效。它将在您的测试概述中提供更好的指示器。异常通常会告诉您测试中存在代码错误。一个断言会告诉你你已经想到了它,并且你可以预期它会出错。这是一个非常好的解决方案,但事实证明,我必须对现有代码进行大量更改才能实现这一点。在您看来,与显式强制转换或修改现有工作代码相比,此解决方案是否增加了一些优势是一个坏主意?@raylodprof这取决于实际情况,在没有看到实际代码的情况下很难进行调用。如果你只是为了测试而选演员,我会说这可能不值得努力去改变,因为你说这需要很大的努力。但是,如果您正在使用真实的代码,这可能是一个问题(目前来看,
MonkeyFinger
完全可能是一只
MonkeyFinger
返回一只
Hand
,手上有
HumanFinger
,而不是
MonkeyFinger
)。使用模板意味着您可以保证从
猴子的手上获得
MonkeyFinger
。这是一个非常好的解决方案,但事实证明,我必须对现有代码进行大量更改才能实现这一点。在您看来,与显式强制转换或修改现有工作代码相比,此解决方案是否增加了一些优势是一个坏主意?@raylodprof这取决于实际情况,在没有看到实际代码的情况下很难进行调用。如果你只是为了测试而选演员,我会说这可能不值得努力去改变,因为你说这需要很大的努力。然而,如果你在铸造你的真实代码,t