【问题标题】:Ensure Variable Initialization C#确保变量初始化 C#
【发布时间】:2015-05-20 18:00:35
【问题描述】:

考虑这段代码:

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

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

在函数内部,我想知道在函数调用之前是否已将值发送到变量 1 和变量 2,

即使已发送 DEFAULT 值,也没关系(字符串为 null,int 为 0)

【问题讨论】:

  • 我认为这里的元答案是“所以不要那样做”。确保所有变量都在构造函数中初始化。
  • 如果我有两个函数怎么办。 F1 和 F2,每个都使用两个变量。但是对于 F1,我必须确保函数的调用者已经为变量设置了值,即使这些值为空。对于F2我不管,我不想强​​迫他在构造函数中发送一些东西!
  • 如果 F1 需要 调用者 设置变量,为什么不将它们作为参数传递给 F1?
  • 这是关于清洁代码、凝聚力、我将变量 1 和变量 2 用于多个其他函数的事实,但只有在某些部分我想在它们没有被初始化的情况下抛出异常等等。 ..
  • 如果您需要设置变量 1 和变量 2 以使 F1 运行,如果它们不是,您的对象处于不一致的状态。因此,您必须在对象准备好使用之前设置它们。也许你想分解你的对象来分解需求?

标签: c# .net variables instance-variables


【解决方案1】:

考虑使用这样的简单包装器:

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
    }
}

您可以更进一步,将 throw Exception 或 contract 添加到 getter,因此如果有人尝试访问未初始化的值,它将引发异常或向您显示警告

【讨论】:

  • 这种方法的缺点是你现在必须说instance.Variable1.Value = "something"才能设置属性。
  • @Sean 你是对的,它可以为你省去在任何你想要一个标志的地方的冗长和重复。
  • @Sean nope,AFAIK 您可以覆盖强制转换和比较运算符,以便您可以进行简单的赋值,例如 Variable1="something" 并且与初始类型 (T) 进行比较不会很痛苦。你真正缺乏的是记忆
  • @AlexVoskresenskiy - 我知道,但你没有在答案中提到这一点!
  • 我喜欢。但我不允许外部“力量”设置“WasAssigned”
【解决方案2】:

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

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

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

自动属性隐藏生成的字段,但有一个。所以同样的规则适用。

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

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

private Yourtype() { }

如果只需要初始化/检查属性/字段的子集,@Sean 和 @Alex 的答案中描述了其他替代方案。但这隐藏了一些开销(每个属性/字段一个 bool 和一些间接)。

【讨论】:

    【解决方案3】:

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

    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 来检查它是否已设置。

    【讨论】:

      【解决方案4】:

      你可以简单地检查两个变量,看看它们是否在你的函数中分配了任何值

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

      【讨论】:

      • 如果Variable1null,这是否意味着有人初始化了这个值?
      • 如果你想在运行时检查类型的默认值,你应该使用:stackoverflow.com/questions/1281161/…
      • 我不想检查默认值。我想检查在函数调用之前是否有人向 var 发送了一些东西,即使它是 NULL 或零或每种类型的任何默认值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-11
      • 2015-04-22
      • 2014-05-19
      • 1970-01-01
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      相关资源
      最近更新 更多