这是';pattern';好的,或者有更好的方法

本文关键字:更好 方法 好的 pattern 这是 或者 | 更新日期: 2023-09-27 18:24:32

我的应用程序中有几个类(只是一个片段):

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);
}

这是';pattern';好的,或者有更好的方法

如果没有关于这些类型的更具体的信息(包括它们的语义、对它们代码的访问等),我认为这种模式通常是动态调度的候选者。例如:

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,但它们是否适合这份工作取决于你。

这取决于您希望从代码中得到什么样的行为。如果将类Element中的SpecificProgramCall()方法声明为虚拟方法,则可以在派生类中重写它。在基类中,您可以抛出错误,也可以优雅地处理它。这可以简化调用SpecificProgramCall的代码。

例如,如果SpecificProgramCall返回一个对象,那么在基类中可以返回null,在派生类中可以返回一个物体。然后,您所要做的就是检查SpecificProgramCall的结果是否为null。

如果您使用多态性,那么代码中的某个地方必须具有责任性。你想把它放在哪里取决于你自己,最终取决于程序其余部分的结构。