确保变量初始化 C#

7

请考虑以下代码:

public string Variable1 { get; set;}
public int Variable2 { get; set;}

public void Function()
{
 // Has been Variable1 Initialized?
}

在函数内部,我想知道在函数调用之前是否已经发送了值到Variable1和Variable2。
即使发送了默认值,也没关系(字符串为null,整数为0)。

4
我认为这里的元答案是“那就别这么做”。确保在构造函数中初始化所有变量。 - Martijn
如果我有两个函数F1和F2,它们都使用两个变量。但对于F1,我必须确保调用者已经设置了变量的值,即使这些值为空。对于F2,我不在乎,我不想强制他在构造函数中发送任何东西! - Cătălin Rădoi
如果在调用F1函数之前需要调用者设置变量,为什么不直接将它们作为参数传递给F1呢? - Martijn
这是关于清晰代码、内聚性的问题,我在多个其他函数中使用Variable1和Variable2,但只有在某些部分中,如果它们没有被初始化,我才想抛出异常等等... - Cătălin Rădoi
如果你需要设置Variable1和Variable2才能运行F1,如果它们没有被设置,那么你的对象状态就是不一致的。因此,在对象准备好使用之前,你必须先设置它们。也许你想要分解你的对象以拆分出这些要求? - Martijn
4个回答

8
考虑使用一个简单的包装器,如下所示:
public struct AssignableProperty<T>
{
    private T _value;

    public T Value
    {
        get { return _value; }
        set
        {
            WasAssigned = true;
            _value = value;
        }
    }

    public bool WasAssigned { get; private set; }

    public static implicit operator AssignableProperty<T>(T data)
    {
        return new AssignableProperty<T>() { Value = data };
    }

    public static bool operator ==(AssignableProperty<T> initial, T data)
    {
        return initial.Value.Equals(data);
    }

    public static bool operator !=(AssignableProperty<T> initial, T data)
    {
        return !initial.Value.Equals(data);
    }

    public override string ToString()
    {
        return Value.ToString();
    }
}

然后你的类会变成这样:
public class Test
{
    public AssignableProperty<string> Variable1 { get; set; }
    public AssignableProperty<int> Variable2 { get; set; }

    public void Function()
    {
        if(Variable1.WasAssigned&&Variable2.WasAssigned)
            //do stuff
    }
}

你可以更进一步地,在getters中添加throw Exception或contract,这样如果有人试图访问未初始化的值,它将抛出异常或显示警告。

1
@Sean 不,据我所知,您可以重写强制转换和比较运算符,以便您可以进行简单的赋值,例如Variable1 =“something”,并且与初始类型(T)的比较不会很麻烦。您真正缺乏的是内存。 - Alex Voskresenskiy
@AlexVoskresenskiy - 我知道,但你在答案中没有提到这点! - Sean
2
我喜欢它。但我不会允许外部“力量”设置“WasAssigned”。 - Noel Widmer
巧妙的小解决方案 - DGibbs
@Noel 是的,除非你将 WasAssigned 的 setter 设置为 private。 - Kryptos
显示剩余6条评论

2

关于C#中默认值的基础知识:

当创建一个类(或结构体)的实例时,所有字段都会被初始化为它们各自的默认值。

对于引用类型,它将是null。对于值类型,它将等同于0。这很容易解释,因为内存管理确保新分配的内存被初始化为0x0字节。

自动属性隐藏了生成的字段,但实际上仍然存在。因此同样的规则适用。

现在来回答你的问题,确保值被初始化的最佳方法是为每个字段/属性创建一个参数的构造函数,并隐藏没有参数的默认构造函数:

public Yourtype(String param1, Int32 param2)
{
    this.Variable1 = param1;
    this.Variable2 = param2;
}

private Yourtype() { }

如果只需要初始化/检查属性/字段的子集,则可以参考@Sean和@Alex的回答中提到的其他替代方法。但这会隐藏一些开销(每个属性/字段一个bool和一些间接性)。

0

对于引用类型,您需要添加一个标志:

string m_Variable1;
bool m_IsVariable1Set;

public string Variable1
{
  get{return m_Variable1;}
  set{m_IsVariable1Set = true; m_Variable1 = value;}
}

对于值类型,您可以使用可空值

int? m_Variable2;

int Variable2
{
  get{return m_Variable2.GetValueOrDefault();}
  set{m_Variable2 = value;}
}

你可以使用m_Variable2.HasValue来检查它是否已被设置。


-2

你可以在函数中对这两个变量进行检查,看它们是否被赋值了任何值。

public void Function()
{

    if (String.IsNullOrEmpty(Variable1) && Variable2 ==0 )
    {
      // Variables are not assigned
    }

}

1
如果Variable1null,那是否意味着有人初始化了该值? - Yuval Itzchakov
如果您想在运行时检查类型的默认值,应使用以下内容:https://dev59.com/3nM_5IYBdhLWcg3wq1CF - Noel Widmer
我不想检查默认值。我想检查在函数调用之前,是否有人向变量发送了任何东西,即使是NULL或零或每种类型的任何默认值。 - Cătălin Rădoi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接