• 【设计原则和建议】 方法输入参数


    个人在多年的开发中对设计有一些自己的想法,在此总结出一些规则希望和大家共同探讨

    当然很多设计大家应该已经知道了,当然对于某些设计可能每个人有不同的看法

    本系列文章不是为了讨论基本的语法,而是介绍和讨论一些设计的规则


    1.在允许的情况下,优先使用父类作为参数类型

    其好处是允许该函数有更大的适用范围,有更多的第三方可以调用该方法 (原来持有父类和其他子类变量的第三方现在也可以调用了)

    (可别为了更大的参数范围把变量都声明为Object了)

     class InputParameter
    {
    //如果可以 参数类型优先选择父类
    public void Method1(IEnumerable<string> p)//good
    {
    }
    public void Method1(List<string> p)//bad
    {
    }
    }


    2.如果该方法是公开方法,那么建议检查输入参数是否有效

    其好处是,函数不会抛出莫名其妙的“为将对象引用到设置对象的实例” (现在获得的是更准确的信息)

        {
    public void Method1(string userName)
    {
    if (userName == null)
    {
    throw new ArgumentNullException("userName");
    }
    //在使用userName之前最好进行检查,userName的值是否合法
    }
    }


    3.如果输入参数不合法,建议终止当前执行并抛出异常

    (代码如上图所示)既然输入参数非法,那么一定要停止程序的执行,以免在错误的道路上越走越远:)

        class InputParameter
    {
    public void Method1(string userName)
    {
    if (userName == null)
    {
    throw new ArgumentNullException("userName");
    }
    if (userName.Length <= 5)
    {
    throw new ArgumentOutOfRangeException("userName", "userName 必须大于5个字符");
    }
    //在使用userName之前最好进行检查,userName的值是否合法
    }
    }


    4.如果可以,参数类型要尽可能的准确

    准确的参数类型有利于用户知道调用规则 以下面两个例子

    如果是string 格式的时间,那么用户就猜不到时间格式了 (时间格式和当前线程的区域有关,也许是 yyyy-MM-dd 也许是 dd/MM/yyyy)

    换成DateTime就不会传入错误的时间格式了

        class InputParameter
    {
    public void Method1(Guid id)//good
    {
    }
    public void Method1(string id)//bad
    {
    }
    public void Method2(DateTime createdTime)//good
    {
    }
    public void Method2(string createdTime)//bad
    {
    }
    }


    5.在有重载的时候,最好保证参数顺序 

    好处就是调用的时候方便,开发这边也方便

        class InputParameter
    {
    public void Method1(Guid id)
    {
    }
    public void Method1(Guid id, int type)//good
    {
    }
    public void Method1(int type, Guid id)//bad
    {
    }
    }


    6.如果有params参数,那么把它放在最后
     

    7.适当使用默认参数,可以减少开发的成本

     public void Method1(Guid id, int type = 1) 
    {
    }


    8.参数名字个人有个人的标准,我个人推荐骆驼命名法
     

    9.移除一切没有被用到的参数,不要为了以后的扩展预留参数,因为通过重构添加参数的方式是很方便的

    10.如果可以,避免使用ref和out参数

    原因是含有ref和out参数的方法较难和其他方法协作,集成'而且某些不了解该参数行为的人可能会误用该方法;为了更好的设计,建议是不要使用ref和out

    也不是完全禁止ref和out,有的时候为了性能原因还是会使用ref和out,以下就是一个例子

                string s = "123";
    int i = 0;
    int.TryParse(s,out i);//性能很好,判断字符串是否合法的代码也简单
    i = int.Parse(s);//没有发生异常的时候没啥问题....


    11.如果有若干个同类型同含义对象,建议使用params参数

       public class BadRepeatArguments
    {
    // Violates rule: ReplaceRepetitiveArgumentsWithParamsArray.
    public void VariableArguments(object obj1, object obj2, object obj3, object obj4) {}
    public void VariableArguments(object obj1, object obj2, object obj3, object obj4, object obj5) {}
    }

    public class GoodRepeatArguments
    {
    public void VariableArguments(object obj1) {}
    public void VariableArguments(object obj1, object obj2) {}
    public void VariableArguments(object obj1, object obj2, object obj3) {}
    public void VariableArguments(params Object[] arg) {}
    }



    如果你想通过某种方式把参数传递到函数内,可是因为种种原因又不能修改方法签名,那么可以采用以下方法

    • 第三方类的静态成员,包括Session Cache等
    • 如果现有参数类型是类或者结构体,可以直接修改它
    • CallContext (该做法不会影响到现有类定义,也不会因为把数据放在共享空间导致冲突)

    参考以下代码

        class InputParameter
    {
    public void Method1()
    {
    CallContext.LogicalSetData("parameter1", DateTime.Now);
    Method2();
    }
    public void Method2()
    {
    var createdTime = Convert.ToDateTime(CallContext.LogicalGetData("parameter1"));
    }
    }


    许多内容引用自MSDN,FxCop 和其他第三方文章..
    因为本人水平有限,如有遗漏或谬误,还请各位高手指正

  • 相关阅读:
    可惜CodeSmith不直接支持Oracle数据库对象...
    Windows Vista
    关于Web Service ...
    他赚了多少钱?
    关于CodeSmith中模板的属性编辑...
    关于Session超时...
    奇怪的CheckBoxList...
    Devdays 2006 China | 微软开发者日
    第二阶段冲刺第一次会议
    冲刺阶段第一天
  • 原文地址:https://www.cnblogs.com/PurpleTide/p/2206629.html
Copyright © 2020-2023  润新知