赋值语句的效率问题,可能只是将变量赋值给自身

本文关键字:变量 赋值 效率 问题 赋值语句 | 更新日期: 2023-09-27 18:06:51

问题:将变量赋值给自身时是否会对性能造成重大影响?

虽然代码可以很容易地更改,以避免将变量赋值给自身或使用标志来检测应该如何赋值…我喜欢使用空合并运算符,使初始化代码更简洁。考虑下面的代码:

   public class MyObject
   {
      public string MyString { get; set; }
   }
   public class Worker
   {
      Dictionary<int, string> m_cache = new Dictionary<string, string>();
      public void Assign(ref MyObject obj)
      {
         string tmp = null;
         if (some condition)
         {
            //can't pass in MyObject.MyString to out param, so we need to use tmp
            m_cache.TryGetValue("SomeKey", out tmp); //assumption: key is guaranteed to exist if condition is met
         }    
         else
         {
             obj.MyString = MagicFinder(); //returns the string we are after
         }
         //finally, assign MyString property
         obj.MyString = tmp ?? obj.MyString; 
         //is there a significant performance hit here that is worth changing 
         //it to the following?
         if (!string.IsEmptyOrNull(tmp))
         {
             obj.MyString = tmp;
         }
      }
   }

赋值语句的效率问题,可能只是将变量赋值给自身

你的问题似乎可以归结为这一部分:

//finally, assign MyString property
obj.MyString = tmp ?? obj.MyString; 

:

//is there a significant performance hit here that is worth changing 
//it to the following?
if (!string.IsNullOrEmpty(tmp))
{
        obj.MyString = tmp;
}
然而,要意识到这两个版本是不一样的。在第一种情况下(使用null合并操作),可以将obj.MyString分配给string.Empty。第二种情况显式地防止了这种情况,因为它是根据string.IsNullOrEmpty进行检查的,这将阻止非空字符串的赋值。

由于行为不同,我想说这不是优化,而是行为改变。这是否合适取决于指定此方法来演示的行为。空字符串应该如何处理?这应该是决定因素。

话虽这么说,如果你要做一个显式的null检查,性能将是几乎相同的-我建议在这里选择可维护性和可读性-对我来说,第一个版本更简单,因为它简短而清晰。


另外,看看你的代码,我认为把赋值放到语句中会简单得多。这将使代码更易于维护(并且更高效,让你的老板高兴…):

  public void Assign(ref MyObject obj)
  {         
     if (some condition)
     {
        string tmp = null;
        //can't pass in MyObject.MyString to out param, so we need to use tmp
        m_cache.TryGetValue("SomeKey", out tmp); //assumption: key is guaranteed to exist if condition is met
        obj.MyString = tmp;
     }    
     else
     {
         obj.MyString = MagicFinder(); //returns the string we are after
     }
  }

给定代码中的假设(如果条件为真,键将始终存在于缓存中),您甚至可以将其简化为:

  public void Assign(MyObject obj) // No reason to pass by ref...
  {         
     obj.MyString = someCondition ? m_cache["SomeKey"] : MagicFinder();
  }

你不应该担心,影响应该是最小的。但是,考虑一下有多少人实际上知道null合并操作符。就我个人而言,我觉得后者更具可读性,你不必考虑它的意思。

检查字符串是否为null或空的性能问题不是直接的问题,但是您可以将代码修改得更简洁,我认为:

string tmp = null;
if (some condition)
{
    m_cache.TryGetValue("SomeKey", out tmp); 
}    
if (string.IsNullOrEmpty(tmp))
{
    tmp = MagicFinder();
}    
obj.MyString = tmp;

"过早优化是万恶之源。"

换句话说,我怀疑任何理论答案都不能代表现实世界的性能,除非你碰巧知道它是如何编译成字节码的…创建一个快速而粗糙的测试框架,使用随机值(null或有效字符串)运行1000次,并自己测量性能如何?

编辑:补充一句,如果性能有很大的不同,那么它在大计划中会很重要,我会感到相当惊讶。首先考虑易读性(尽管您可以争论两者都支持:))