赋值语句的效率问题,可能只是将变量赋值给自身
本文关键字:变量 赋值 效率 问题 赋值语句 | 更新日期: 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次,并自己测量性能如何?
编辑:补充一句,如果性能有很大的不同,那么它在大计划中会很重要,我会感到相当惊讶。首先考虑易读性(尽管您可以争论两者都支持:))