问题描述
我看到String.Intern
实际上将一个字符串添加到内部池,而String.IsInterned
将返回对该对应的实习字符串的引用。这让我感到奇怪:
- 为什么
IsInterned
返回所引用的实习字符串而不返回bool
来指示给定的字符串到目前为止是否已被实习?我觉得 Is 表示法很有趣。 - 在哪种情况下,下面的代码将返回true?
bool InternCheck(string s)
{
string internedString = String.IsInterned(s);
return internedString != null && !String.Equals(internedString,s);
}
解决方法
为什么IsInterned返回引用的被阻止的字符串,而不是布尔值,指示到目前为止是否已对给定的字符串进行了阻止?我觉得Is表示法很有趣。
对于明确的“为什么”?您需要问微软。但是,请将IsInterned()
与相似的HashSet<T>.Add()
(尽管功能上当然有所不同)进行比较。即拥有一种检查某项是否正确的方法很方便,如果是,则提供所需的值作为返回所需信息的一部分。
为什么这种方法不遵循TryXXX()
模式,再次……您不得不询问Microsoft,但我们可以很容易地猜到。显然,该方法可能返回了bool
并提供了字符串引用作为out
参数。但是请注意,这里我们知道值类型是可为空的引用,因此可以将null作为表示不存在的适当方法,这与实现TryXXX()
方法的各种类型不同。
在哪种情况下,下面的代码将返回true?
我看不到该代码将如何返回true
。如果该字符串没有被插入,它将返回false
,如果被插入,则被插入的字符串必须始终等于传入的字符串,因此!string.Equals(...)
也将是{{ 1}}。
您是否有其他理由?
,让我们想象一下String.IsInterned
方法是否在哪里返回bool
。然后,您从调用bool whoopie = String.IsInterned(s);
中所知道的就是,字符串的值与被插入的字符串相同。没有迹象表明您对实习字符串具有相同的引用。
现在,实习的重点是降低内存压力。您知道您正在创建很多类似的字符串,并且要确保不会阻塞内存。
进行实习的成本要比消耗RAM的成本低。
因此,假设返回String.IsInterned
,返回bool
。
由于您不知道是否有实习参考,否则就没有必要进行实习了,您最终会写很多代码:
if (String.IsInterned(s))
{
s = String.GetInterned(s);
}
或者:
s = String.IsInterned(s) ? String.GetInterned(s) : s;
String.GetInterned
也是一种假设方法。
通过IsInterned
的实际实现,此代码变得稍微简单一些:
s = String.IsInterned(s) ?? s;
让我们看看是否可以改进此设计。
如果我尝试实现TryGetInterned
风格的运算符,则可以这样实现:
public static bool TryGetInterned(this string input,out string output)
{
string intermediate = String.IsInterned(input);
output = intermediate ?? input;
return intermediate != null;
}
这段代码可以很好地工作,但是会导致这种代码重复:
string s = "Hello World";
if (s.TryGetInterned(out string s2))
Console.WriteLine(s2); // `s` is interned
else
Console.WriteLine(s2); // `s` is NOT interned
这似乎毫无意义。
将此与当前的IsInterned
方法进行比较:
string s = "Hello World";
s = String.IsInterned(s) ?? s;
Console.WriteLine(s);
简单得多。
在某些情况下,我可以考虑改进的唯一实现是:
public static string GetIsInternedOrSelf(this string input)
=> String.IsInterned(input) ?? input;
现在我有了这个
string s = "Hello World";
s = s.GetIsInternedOrSelf();
Console.WriteLine(s);
这是一个改进,但是我们已经失去了知道字符串是否被插入的功能。
最重要的是,我认为String.IsInterned
的设计可能会尽善尽美。