【问题标题】:Use "Optional, DefaultParameterValue" attribute, or not?是否使用“Optional, DefaultParameterValue”属性?
【发布时间】:2017-08-19 04:41:46
【问题描述】:

使用OptionalDefaultParameterValue 属性和不使用它们有什么区别吗?

public void Test1([Optional, DefaultParameterValue("param1")] string p1, [Optional, DefaultParameterValue("param2")] string p2)
{
}

public void Test2(string p1= "param1", string p2= "param2")
{
}

两者都有效:

Test1(p2: "aaa");
Test2(p2: "aaa");

【问题讨论】:

  • 好问题,甚至不知道这些属性存在。
  • 有,但是你在写这样的代码的时候,在实践中不太可能遇到。 [可选] 属性在 C# 版本 4 中被劫持,以帮助编写更简单的 COM 互操作代码。参数必须是没有默认值的对象才能看到它,然后调用者传递 Type.Missing。使用提供的语法糖当然总是最好的。

标签: c# c#-4.0 optional-parameters


【解决方案1】:

它们的编译方式相同,并且编译器可以正常工作。唯一的区别就是少了using System.Runtime.InteropServices;,代码更容易阅读。

作为参考,IL 是:

.method public hidebysig instance void TheName([opt] string p1,
    [opt] string p2) cil managed
{
    .param [1] = string('param1')
    .param [2] = string('param2')
    .maxstack 8
    L_0000: ret 
}

TheName 是唯一改变的地方。

【讨论】:

  • 检查@hvd 的答案。虽然它们的工作方式几乎相同,但 InteropServices 显然不是它们唯一的区别
【解决方案2】:

不同之处在于,通过显式使用属性,编译器不会对类型要求强制执行相同的严格性。

public class C {
  // accepted
  public void f([Optional, DefaultParameterValue(1)] object i) { }

  // error CS1763: 'i' is of type 'object'. A default parameter value of a reference type other than string can only be initialized with null
  //public void g(object i = 1) { }

  // works, calls f(1)
  public void h() { f(); }
}

请注意,即使使用DefaultParameterValue,您也不会丢弃类型安全:如果类型不兼容,这仍会被标记。

public class C {
  // error CS1908: The type of the argument to the DefaultParameterValue attribute must match the parameter type
  //public void f([Optional, DefaultParameterValue("abc")] int i) { }
}

【讨论】:

    【解决方案3】:
    namespace System.Runtime.InteropServices {
    
        using System;
    
        //
        // The DefaultParameterValueAttribute is used in C# to set 
        // the default value for parameters when calling methods
        // from other languages. This is particularly useful for 
        // methods defined in COM interop interfaces.
        //
        [AttributeUsageAttribute(AttributeTargets.Parameter)]
        public sealed class DefaultParameterValueAttribute : System.Attribute
        {
             public DefaultParameterValueAttribute(object value)
             {
                 this.value = value;
             }
    
             public object Value { get { return this.value; } }
    
             private object value;
        }
    }
    

    他们在做同样的工作。您可以在RoslynReferenceSource 中查看此类内容

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-21
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 2020-07-15
      • 1970-01-01
      • 2022-11-03
      相关资源
      最近更新 更多