【问题标题】:C#: Sane alternative to optional parameter in property?C#:属性中可选参数的合理替代方案?
【发布时间】:2010-11-06 22:42:22
【问题描述】:

给定:具有 SomeNumber 等属性的类,内部可以为 null(即int?),但在外部,您通常不想处理这种特殊情况,并假装它们开始出为零。到目前为止,我们总是返回一个不可为空的版本,即int。我想添加一个选项以获得可为空的版本。

最简单的变体:两个属性。效果很好,但不幸的是,在课堂上出现了很多冗余的选项。外部代码:

return myObject.SomeNumber; // Not nullable.
return myObject.SomeNumber_Nullable; // Nullable.

内部脏,但外部不错的变体:带有可选参数的属性。我还没有发现如何在 C# 中做到这一点; .NET Reflector 似乎省略了不正确的代码。在 VB.NET 中,它看起来像这样:

Private _SomeNumber As Nullable(Of Integer)
Public Property SomeNumber(Optional ByVal AllowNull As Boolean = False) As Nullable(Of Integer)
  Get
    If Not AllowNull AndAlso _SomeNumber Is Nothing
      Return 0
    End If

    Return _SomeNumber
  End Get
  Set(ByVal value As Boolean)
    _SomeNumber = value
  End Set
End Property

外部代码:

return myObject.SomeNumber; // Not nullable.
return myObject.SomeNumber(true); // Nullable.

缺点: * C# 实现是如此丑陋。NET Reflector 甚至似乎都不知道该怎么做, * 我发现参数化属性的一般概念有问题, * 在不可为空的示例中,返回类型与属性的实际行为不匹配——编译器现在认为它可以null,但实际上不能。

还有其他想法吗?

【问题讨论】:

  • 定义“内部”——这是在类内还是在应用程序内?
  • 我想我没有抓住重点,因为很明显你是在向客户公开知识,即......他们必须传递一个布尔值才能得到他们想要的东西。它只是一个 int 有什么害处?如果他们想要在其上调用 Value 的值,他们可以检查它是否具有值。如果不需要 null,请使用 -1,因为这是不可为 null 的 int 类型的常见做法...
  • 内部表示类内;在类外部或不同的程序集中。 -1 作为伪空值对我没有任何好处,因为它是一个有效数字,即可能是实际值。
  • ...而使用标准空类型的原因还不够?消费者要么必须传入一个布尔值,要么必须在类型上调用 Value...我没有看到区别,这里没有抽象任何内容...
  • 当然可以。 int? 允许 null(显然),然后类消费者的代码必须检查它。

标签: .net-3.5 c#-3.0 properties


【解决方案1】:

听起来您正试图过度设计您的课程。一个属性是空的,或者它不是空的,并且它不是客户端检查空的负担。我觉得理解你的 API 是一种负担,对我来说这听起来像:'这个属性永远不会为空。除非你检查它是否真的为空。嗯?

此外,尝试隐藏空值通常不是一个好主意,因为它会隐藏程序中的错误。

【讨论】:

    【解决方案2】:

    属性在 C# 中不能有参数,因此如果要使用属性语法,则需要两个名称不同的属性。

    如果您不希望您的类的用户知道您的字段在内部可能为空,那么如果您控制属性的实现,这将非常简单。将属性的支持字段定义为int? 类型,但将属性类型保留为int

    例如:

    private int? _someNumber = null;
    
    public int SomeNumber { 
      get { return _someNumber.HasValue ? _someNumber.Value : 0; }
      set { _someNumber = value; }
    }
    

    现在,在内部,您始终可以访问 _someNumber.HasValue 以检查是否已设置值。

    但是,当您说“我想添加一个选项以具有可空版本。”时,如果您确实想要一种方式向您的客户公开SomeNumber 是否有一个值,那么你有几个选择:

    • 公开像bool SomeNumberHasValue这样的属性
    • SomeNumber的类型更改为int?
    • 添加第二个属性SomeNumberNullable,其返回类型为int?

    但是,单个属性有时不能返回 int,而在其他时候返回 int?

    另一种选择是使用一种方法来访问该值,如下所示:

    public int? GetSomeNumber(bool canReturnNull)
    {
        if (canReturnNull)
            return _someNumber;
    
        return _someNumber.HasValue ? _someNumber.Value : 0;
    }
    

    实际上,您做了很多工作来让您的客户更容易处理空检查,而不是隐藏值可以为空的事实。有什么好处?

    【讨论】:

    • 我希望该类的用户可以选择(但不是通常)访问可以返回 null 的属性版本,这种效果很像方法中的重载。
    猜你喜欢
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    • 2011-09-15
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    相关资源
    最近更新 更多