-1

I see that String.Intern will actually add a string to the intern-pool and String.IsInterned will return the reference to that corresponding interned string. This makes me wonder:

  1. Why does IsInterned return the referenced interned string and not a bool indicating whether a given string has been interned so far? I feel it's a funny use for an Is notation.
  2. In what case would the code below return true?
bool InternCheck(string s)
{
string internedString = String.IsInterned(s);
return internedString != null && !String.Equals(internedString, s);
}
sean.net
  • 735
  • 8
  • 25
  • As far as the method name is concerned, you're right; it should return a boolean value, but the implementation returns the reference to the passed string in the interned pool. Look at this: https://learn.microsoft.com/en-us/dotnet/api/system.string.isinterned?view=netcore-3.1 – Amit Kumar Nov 05 '20 at 21:26
  • 1
    [Remarks section of `String.IsInterned`](https://learn.microsoft.com/en-us/dotnet/api/system.string.isinterned?view=netcore-3.1#remarks) shows an exact code sample with getting a `bool` value. _This method does not return a Boolean value. If you call the method because you want a Boolean value that indicates whether a particular string is interned, you can use code such as the following._ – Pavel Anikhouski Nov 05 '20 at 21:31
  • See https://stackoverflow.com/a/31028349/224370 for an example of this _very rarely-used_ method. – Ian Mercer Nov 05 '20 at 21:42
  • 1
    Two reasons I can think of, related. One is that it reflects the CLR's string pool design, it does not have a bool test either. The other related one that would worry the CLR designers is thread safety, always a big deal with primitive types. A *false* return in no way can promise that the string isn't interned by the time you use that return value. An example of a method that suffers badly from this TOCTOU race is File.Exists(). Added by popular demand, but it is even worse, you can neither trust a *true* or *false* return. – Hans Passant Nov 05 '20 at 22:55

2 Answers2

2

Why does IsInterned return the referenced interned string and not a bool indicating whether a given string has been interned so far? I feel it's a funny use for an Is notation.

For definitive "why?" you need to ask Microsoft. However, compare IsInterned() with similar (though functionally different of course) HashSet<T>.Add(). I.e. it's convenient to have a method that checks whether something is true, and if it is, provides the value you wanted as part of returning the information you want.

Why this method doesn't follow the TryXXX() pattern, again…you'd have to ask Microsoft, but we can easily guess. Obviously the method could have returned a bool and providing the string reference as an out parameter. But note that here, we know the value type is a nullable reference, and so can be null as an adequate way to indicate non-existence, which is different from the various types that implement TryXXX() methods.

In what case would the code below return true?

I don't see how that code would ever return true. If the string is not interned, it will return false, and if it is interned, then the interned string is necessarily always equal to the string that was passed in, and so !string.Equals(...) would also be false.

Is there some reason you think otherwise?

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
1

Let's imagine if the String.IsInterned method where to return a bool. Then all you'd know from calling bool whoopie = String.IsInterned(s); is that the value of your string is the same as a string that is interned. There is no indication that you have the same reference to the interned string.

Now the point of interning is to hold memory pressure down. You know you're creating a lot of similar strings and you want to ensure that you're not clogging up memory.

There's a cost to interning and that cost better be less than the cost of using up RAM.

So, back to String.IsInterned hypothetically returning a bool.

Since you don't know if you have the interned reference, which you'd want otherwise there's no point in interning, you'd end up writing this code a lot:

if (String.IsInterned(s))
{
    s = String.GetInterned(s);
}

Or:

s = String.IsInterned(s) ? String.GetInterned(s) : s;

String.GetInterned is also a hypothetical method.

With the actual implementation of IsInterned this code becomes slightly simpler:

s = String.IsInterned(s) ?? s;

Let's see if we can improve this design.

If I try to implement a TryGetInterned style of operator I might implement it like this:

public static bool TryGetInterned(this string input, out string output)
{
    string intermediate = String.IsInterned(input);
    output = intermediate ?? input;
    return intermediate != null;
}

This code works perfectly fine, but it leads to this kind of code repetition:

string s = "Hello World";

if (s.TryGetInterned(out string s2))
    Console.WriteLine(s2); // `s` is interned
else
    Console.WriteLine(s2); // `s` is NOT interned

This seems pretty pointless.

Compare this to the current IsInterned method:

string s = "Hello World";
s = String.IsInterned(s) ?? s;
Console.WriteLine(s);

Much simpler.

The only implementation that I could consider an improvement, in some circumstances, is this:

public static string GetIsInternedOrSelf(this string input)
    => String.IsInterned(input) ?? input;

Now I have this:

string s = "Hello World";
s = s.GetIsInternedOrSelf();
Console.WriteLine(s);

It's an improvement, but we've lost the ability to know if the string was interned.

The bottom-line is that I think String.IsInterned is probably as well designed as it could be.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172