我的应用程序中有几个类(只是一个片段):
public abstract class Element {...}
public abstract class Program : Element
{
...
public void SpecificProgramCall();
}
当我知道变量补丁属于子类型时,我使用:
((Program) element).SpecificProgramCall();
或更好:
var patch = patch as Program;
Debug.Assert(patch != null);
patch.SpecificProgramCall();
当我不知道它是否是一个程序时:
var patch = patch as (Program);
if (patch != null)
{
patch.SpecificProgramCall();
}
但是,我的代码(将会)充满了这些结构。有没有更好的方法来实现这个?
示例:
var usedProgramBank = ((SetListSlot) setListSlot).UsedPatch.Parent as ProgramBank;
var key = new Tuple<ProgramBank, Program>(usedProgramBank, ((SetListSlot) setListSlot).UsedPatch as Program);
if (_dict.ContainsKey(key) && !_dict[key].Contains(setListSlot))
{
_dict[key].Add(setListSlot);
}
答案 0 :(得分:1)
这取决于您希望从代码中获得什么样的行为。如果将类Element中的SpecificProgramCall()方法声明为virtual,则可以在派生类中覆盖它。在基类中,您可以抛出错误或正常处理它。这可以简化对SpecificProgramCall调用的代码。
例如,如果SpecificProgramCall返回一个对象,那么在基类中你可以返回null并在派生类中返回一个对象。然后你要做的就是检查SpecificProgramCall的结果是否为空。
如果您正在使用多态,那么您的代码中必须存在问责制。你想把它放在哪里取决于你,最终取决于程序其余部分的结构。
答案 1 :(得分:1)
如果没有关于这些类型的更多具体信息(包括它们的语义,您对代码的访问等),我会说这种模式通常是动态调度的候选者。例如:
public abstract class Element
{
public virtual void MaybeSpecificCall()
{
// nothing in most cases
}
}
public abstract class Program : Element
{
public override void MaybeSpecificCall()
{
base.MaybeSpecificCall();
// but in this specific case, do something
SpecificProgramCall();
}
public void SpecificProgramCall() { /* ... */ }
}
然后你可以在呼叫点做patch.MaybeSpecificCall()
,让动态调度机制决定做某事而什么都不做。
或者,如果你不想搞乱基类,而你只是对没有看到“丑陋”的兴趣感兴趣。类型检查,然后帮助方法可以做到这一点:
static void IfProgram(this Element element, Action<Program> action)
{
var program = element as Program;
if(program != null) action.Invoke(program);
}
而且,再次,您使用patch.IfProgram(x => x.SpecificProgramCall())
来调用它。我个人喜欢lambdas,但他们是否因为这份工作而感到丑陋取决于你。