繁体   English   中英

是否可以在C#中限制可选参数的值?

[英]Is it possible to restrict the values of optional parameters in C#?

C#允许使用可选参数 :如果在调用中省略参数,则可以指定值,然后编译器指定值本身。

例:

public interface IFoo {

    void SomeMethod (int para = 0);

}

这个想法很有用,但问题是可以在类层次结构的不同层次上定义几个“默认值”。 例:

public class SubFoo : IFoo {

    public void SomeMethod (int para = 1) {
        //do something
    }

}

如果有人打电话:

SubFoo sf = new SubFoo ();
sf.SomeMethod ();
Foo f = sf;
f.SomeMethod ();

结果是第一次调用是使用para等于1完成的,第二次调用是使用para等于0 (作为接口)。 这是有道理的,因为编译器添加了默认值,在第一种情况下, this是一个SubFoo因此默认值为1

程序员当然要保持一致性,但是当程序员在过程中间改变他/她的想法并忘记修改所有默认值时,很容易发生这种精神分裂症状。

问题是编译器不会警告正在使用不同的默认值,而这可以通过向上移动类层次结构来检查。 更有些人可能会模仿默认参数:

public class SubFoo2 {

    public virtual void SomeMethod () {
        SomeMethod(1);
    }

    public void SomeMethod (int para) {
        //do something
    }

}

这允许动态绑定,从而一致地覆盖。 因此,需要非常小心如何“实现”默认值。

有没有办法强制执行(例如使用编译器标志)来检查默认值是否一致? 如果不是,至少要警告某些东西不是真的一致会很好。

如果您希望编译时指示方法正在更改可选参数的默认值,那么您将需要使用某种第三方代码分析工具,因为C#本身不提供任何提供方法这样的限制,或任何警告,当它完成。


作为一种解决方法,一种选择是避免使用可选参数值,而是使用多个重载。 由于这里有一个接口,这意味着使用扩展方法,以便在一般情况下仍然定义具有默认值的重载的实现:

public interface IFoo
{
    void SomeMethod(int para);
}

public static class FooExtensions
{
    public static void SomeMethod(this IFoo foo)
    {
        foo.SomeMethod(0);
    }
}

因此,尽管这种方法在技术上仍然允许某人创建名为SomeMethod的扩展(或实例)方法并且不接受任何int参数,但这意味着某人真的需要SomeMethod地主动更改“默认值”。 不需要实现接口来提供默认值,这可能会无意中提供错误的默认值。

那么没有必要的编译时解决方案 - 但是你可以对它进行单元测试(我怀疑你正在认真对待单元测试,如果你提出这样的问题,你经常运行它们)。 我们的想法是创建断言方法,如AssertThatDefaultParametersAreEqual(Type forType) - 查找所有非abstract类(使用反射)并从forType继承,然后遍历已定义默认参数的所有方法:

MethodInfo[] methodInfo = Type.GetType(classType).GetMethods(BindingFlags.OptionalParamBinding | BindingFlags.Invoke);

通过MethodInfo.Name它们进行分组,并在组内检查所有具有默认值的相同参数(可以通过MethodInfo.GetParameters().Where(x => x.IsOptional)获得MethodInfo.GetParameters().Where(x => x.IsOptional) )具有ParameterInfo.DefaultValue的相等属性。

编辑:顺便说一句。 这可能不适用于Mono,因为编译器没有义务发出例如: Optional BindingFlag。

定义const int DefaultPara = 1; 然后使用它而不是硬编码数值。

interface IFoo 
{
    void SomeMethod (int para = DefaultPara);
}

public class SubFoo : IFoo {

    public void SomeMethod (int para = DefaultPara) {
        //do something
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM