C# 如何正确处理'default(T)`,避免原始困扰?

C# 如何正确处理'default(T)`,避免原始困扰?,c#,.net,struct,default,C#,.net,Struct,Default,我想避免对以下struct的原始痴迷。我这样做有两个目标: 使方法签名更诚实 确保无效值不存在 实施: public struct SomeId : IEquatable<SomeId> { public static readonly SomeId Empty = new SomeId(String.Empty); private SomeId(string someId) { Value = someId; } pu

我想避免对以下
struct
的原始痴迷。我这样做有两个目标:

  • 使方法签名更诚实
  • 确保无效值不存在
实施:

public struct SomeId : IEquatable<SomeId>
{
    public static readonly SomeId Empty = new SomeId(String.Empty);

    private SomeId(string someId)
    {
        Value = someId;
    }

    public string Value { get; }

    public static bool operator ==(SomeId left, SomeId right) => left.Equals(right);
    public static bool operator !=(SomeId left, SomeId right) => !(left == right);
    public static implicit operator string(SomeId id) => id.Value;
    public override int GetHashCode() => Value.GetHashCode();
    public override bool Equals(object obj) => Value.Equals(obj);
    public bool Equals(SomeId other) => String.Equals(Value, other.Value, StringComparison.Ordinal);

    public static SomeId? Create(string value)
    {
        if (String.IsNullOrWhiteSpace(value))
        {
            return new SomeId(value);
        }

        return null;
    }
}

。。。但是,每当我访问此属性时,额外的空检查都会让我感到困扰。

你应该在意吗?是的,我想是的。创建零初始化结构非常容易(
default(SomeId)
new SomeId()
new SomeId[n]
),并且您的结构在该状态下语义无效

您有几个选择:

  • getter中的Null合并(您建议的解决方案)。您是对的,如果该字段为空,则总是会导致执行更多的指令。问题是,这些额外的指令(例如load null、比较是否相等、load static字段)是否对执行速度有可测量的影响
  • 检查getter中的
    null
    ,并将字段设置为
    string。如果需要,为空。从技术上讲,它是一个具有副作用的getter(即使数据是封装的),有些人对此有强烈的看法,但你也可以称之为惰性初始化
  • 将默认实例声明为无效,如

Struct很可能用于perf,如果您想要更多的控制,应该使用类。您将失去性能优势?谢谢!我只是想指出,我是那个不会在getter中改变领域的人。。。我会坚持第一种选择。
private string _value;
public string Value => _value ?? String.Empty