【问题标题】:Default value for nullable value in c# 2.0c# 2.0 中可空值的默认值
【发布时间】:2011-11-21 17:01:53
【问题描述】:

使用 C# 2.0,我可以像这样指定默认参数值:

static void Test([DefaultParameterValueAttribute(null)] String x) {}

由于此 C# 4.0 语法不可用:

static void Test(String x = null) {}

那么,值类型是否有 C# 2.0 等效项?例如:

static void Test(int? x = null) {}

以下尝试无法编译。

// error CS1908: The type of the argument to the DefaultValue attribute must match the parameter type
static void Test([DefaultParameterValueAttribute(null)] int? x) {}

// error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression
static void Test([DefaultParameterValueAttribute(new Nullable<int>())] int? x) {}

【问题讨论】:

  • 这是为了开发一个供外部语言调用的库吗?
  • 是的,它是一个图书馆。该代码实际上是使用 CSharpCodeProvider 生成的,并且只是调用到专有 C++ 变体类的 C++/CLI 接口。 “企业”。

标签: c# .net c#-2.0


【解决方案1】:

很遗憾,旧版本的 C# 编译器不支持此功能。

C# 4.0 编译器编译这个:

public static void Foo(int? value = null)

进入:

public static void Foo([Optional, DefaultParameterValue(null)] int? value)

这实际上与您的第一次尝试相同(另外添加了 OptionalAttribute),C# 2 编译器在 CS1908 上出错,因为该版本的编译器不直接支持。

如果您需要支持 C# 2,在这种情况下,我建议您添加一个重载方法:

static void Test()
{
    Test(null);
}
static void Test(int? x)
{
    // ..

【讨论】:

    【解决方案2】:

    里德当然是正确的;我只是想我会添加一个关于角落案例的有趣事实。在 C# 4.0 中,您可以说:(对于结构类型 S)

    void M1(S x = default(S)) {}
    void M2(S? x = null) {}
    void M3(S? x = default(S?)) {}
    

    但奇怪的是你不能说

    void M4(S? x = default(S)) {}
    

    在前三种情况下,我们可以简单地发出表示“可​​选值是形式参数类型的默认值”的元数据。但在第四种情况下,可选值是不同类型的默认值。没有一种明显的方法可以将这种事实编码到元数据中。我们没有为如何编码这样的事实制定跨语言的一致规则,而是在 C# 中简单地将其设为非法。这可能是一个罕见的极端情况,所以不会有太大的损失。

    【讨论】:

      【解决方案3】:

      显然你不能使用这个属性。

      如您所知,属性参数在编译时被“序列化”为元数据——因此您需要常量表达式。由于编译器不喜欢'null',所以你没有选择。

      你可以做的是 - 重载 - 定义另一个没有参数的 Text 方法,它使用 null 调用你的 Text 方法

      【讨论】:

        【解决方案4】:

        这是否有效:[DefaultParameterValueAttribute((int?)null)]? 试过 - 这也不起作用(

        【讨论】:

        • 是的,您确实可以强制转换空引用。由于其他原因,它不起作用。
        • 实际上在 Nullable 的情况下 - 我们可以使用强制转换,因为它是一个特殊的结构(不是类)。例如,此 e 表达式有效:int? a = isSomethingTrue ? (int?)null : 1;。回到原来的问题......似乎 DefaultParameterValueAttribute '认为' struct 不能有空值 - 看起来像一个错误。
        • 此外,我们仍然有能力以某种疯狂的方式解决问题:1) 使用带有 object 参数的构造函数定义自定义属性 CustomDefaultParameterValueAttribute : Attribute,2) 将此新属性应用于目标参数. 3) 创建一个将使用 Mono.Cecil 打开编译库并将 CustomDefaultParameterValueAttribute 替换为 DefaultParameterValueAttribute 的新项目。但正如您所了解的,定义另一个无参数方法要容易得多:)
        【解决方案5】:

        我认为应该是:

        static void Text(int? x = default(int?));
        

        【讨论】:

        • 那是针对 C# 4.0 的。他在问在 C# 2.0 中使用属性时的等价物是什么。
        • 啊。我误解了这个问题。我以为他是在说它在 4.0 中不起作用。对不起。
        猜你喜欢
        • 1970-01-01
        • 2011-01-24
        • 2013-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-17
        • 1970-01-01
        相关资源
        最近更新 更多