【问题标题】:Overwriting Default values in C# structs覆盖 C# 结构中的默认值
【发布时间】:2010-02-02 04:31:53
【问题描述】:

对于作业,我必须使用结构在 C# 中编写 Tribool 类。只有三种可能的 tribool,True、False 和 Unknown,我将它们声明为静态只读。像这样:

public static readonly Tribool True, False, Unknown;

我需要我的默认构造函数来提供一个 False Tribool,但我不知道该怎么做。我已经尝试过Tribool() { this = False; }Tribool() { False; },但我不断收到“结构不能包含显式无参数构造函数”错误。

指定 Tribool 的默认构造函数应提供 False Tribool。否则,用户将无法创建任何其他 Tribool。我现在真的不知道该怎么办。任何建议将不胜感激。谢谢。

【问题讨论】:

  • 就我自己而言,我总是按此顺序创建状态Unknown, False, True。因此,未初始化的 Tribool 默认状态为未知。

标签: c# struct


【解决方案1】:

只是在 Jason 的回答中添加一点:仔细设计您的结构,以便默认值有意义。例如,考虑Nullable<T> 结构。期望的行为是当你说

Nullable<int> x = new Nullable<int>(); // default constructor

结果值在逻辑上为空。我们如何做到这一点?结构体的定义如下:

struct Nullable<T> 
{
    private readonly T value;
    private readonly bool hasValue;
    public Nullable(T value)
    { 
        this.value = value;
        this.hasValue = true;
    }
    ...

因此,当默认构造函数运行时,hasValue 会自动设置为 false,并且 value 会设置为 T 的默认值。将 hasValue 设置为 false 的可空对象被视为 null,这是所需的行为。这就是为什么 bool 是 hasValue 而不是 isNull

【讨论】:

  • 当我运行Nullable&lt;int&gt; i = new Nullable&lt;int&gt;(); Console.WriteLine( i.Value); 代码时,第二行出现异常。您在答案中提到value is set to default value of T。基于此i.Value 应该是0。但它抛出了一个异常{"Nullable object must have a value."}。为什么?此外,inull。为什么?附言我知道Nullable 类型。只是想知道这种行为是如何实现的?
  • 该字段为零。属性访问或抛出。
  • 我不知道你所说的属性访问或抛出是什么意思
  • @gmailuser - 他的意思是“属性访问器抛出”,例如public T Value {get { if (!hasValue) throw... } }
  • 哇.. 所以有新功能自动更正:) 但是,无论如何谢谢。您的时间总是值得赞赏的。对我来说,有时很难理解知名程序员的解释。
【解决方案2】:

正如错误告诉你的那样,你绝对不能有一个结构的无参数实例构造函数。请参阅 C# 3.0 语言规范的 §11.3.8:

与类不同,结构不允许声明无参数的实例构造函数。

该语言为您提供了一种称为默认构造函数的语言。此构造函数返回结构体的值,其中字段已设置为默认值。

现在,您可以做的是让结构的默认值代表False 值。我会把细节留给你。

【讨论】:

  • 非常感谢您的提议。只是想知道,如果我不尝试覆盖默认构造函数,默认值会是什么?我想我可能没有完全理解这项任务。有人提到我应该有一个系统来表示 Tribool 类本身内部的 True/False/Unknown,而不是使用公共静态只读常量作为值,而且我不应该需要构造函数,因为它没有做任何有意义的事情......我是不太清楚这意味着什么,以及我将如何定义 True/False/Unknown tribools。如果您能向我解释一下,我将不胜感激。谢谢!
  • 是的,关键是找到一种表示TriBool的方法。这完全取决于您,“正确的方式”在很大程度上取决于您与TriBool 的其他关系。但也有一些可能: 1. 内部使用int 表示TriBool,“false”对应0,“true”对应1,“unknown”对应-1。或者,在内部使用两个bool,一个称为value,另一个称为unknown,其中value代表“真”或“假”,具体取决于它是true还是false,但是仅当unknownfalse 时,否则实例表示“未知”。
  • 最后,你应该在我回答的倒数第二句话的上下文中考虑这些表示,或者你想出的任何东西。
  • 非常感谢您的帮助!我想我知道现在该做什么了。最后一个问题——如果我使用 int 定义静态 Tribool True,我知道将其值设置为 1。但我会在哪里声明呢?我试过 public static readonly Tribool True {value = 1;} 但似乎我又做错了。你能给我一个提示我做错了什么吗?再次感谢。
  • 您做错了什么是您尝试使用对象初始化器语法来初始化 value 但您可能尚未将 value 声明为属性。没关系。所以你需要一种不同的方法。我想到了几个选择。 1. 你可以定义一个私有构造函数TriBool(int value) 来设置this.value 的值,然后说public static readonly TriBool True = new TriBool(1); 2. 你可以定义一个静态构造函数static TriBool() { True.value = 1; } 3. 继续定义value 为一个财产。坦率地说,我赞成选项 1。
【解决方案3】:

游戏有点晚了,但是你有什么理由不使用枚举?

毕竟,如果你只需要一个 Trinary 值,那么这个结构就太过分了

public enum Tribool{
    Unknown =0,
    True = -1,
    False = 1
}

【讨论】:

  • 您不能在枚举上重载运算符。如果您使用了结构,那么您可以重载 operator ~operator &amp;operator |operator ^,并为三路逻辑提供适当的行为。
猜你喜欢
  • 1970-01-01
  • 2011-12-20
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多