-
TL;DR: A (relatively) simple BinaryExpression equality-comparing two string instances (as ConstantExpressions) will evaluate to different results solely depending on whether the involved strings are interned or not interned. Is this a bug, or is it intended behavior? If it is intended behavior, where is it documented? Lets create a simple Equality-comparison expression which compares two string values: using System;
using System.Linq.Expressions;
var strLeft = "foobar";
var strRight = new string(new char[] { 'f', 'o', 'o', 'b', 'a', 'r' });
var left = Expression.Constant(strLeft, typeof(object));
var right = Expression.Constant(strRight, typeof(string));
var eq = Expression.Equal(left, right);
var lam = Expression.Lambda(eq);
var result = lam.Compile().DynamicInvoke();
Console.WriteLine(result); strLeft (a string literal) is an interned string. strRight is not an interned string. Crucially important is that the left ConstantExpression is typed as object, not as string. Executing this will yield a However, now lets change strLeft also to a non-interned string (reminder: strLeft is the one used in the object-typed ConstantExpression): var strLeft = new string(new char[] { 'f', 'o', 'o', 'b', 'a', 'r' });
var strRight = new string(new char[] { 'f', 'o', 'o', 'b', 'a', 'r' });
... Both strLeft and strRight are now non-interned string instances. But they are still equal. Yet, now the equality expression with the left-hand side typed as object will unexpectedly and surprisingly evaluate to If i "manually" intern strLeft like so: var strLeft = new string(new char[] { 'f', 'o', 'o', 'b', 'a', 'r' });
var strRight = new string(new char[] { 'f', 'o', 'o', 'b', 'a', 'r' });
strLeft = string.Intern(strLeft);
... the equality expression will now again correctly evaluate to What is going on here? Why does the result of the expression evaluation depend on whether strLeft is an interned string or not? Do i lack a fundamental understanding of how System.Linq.Expressions is supposed to work? Or is this a bug? (My apologies if this has been reported elsewhere already. I wasn't able to find any other report about this here in the discussion or issues section; not sure what other terms to search for than something along the lines of "expression string intern" or alike.) |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
@elgonzo your expression compares objects by reference, |
Beta Was this translation helpful? Give feedback.
-
If that were the case, the three cases i outlined in my report should all evaluate to false (because strLeft and strRight are separate string instances in every of these three cases), no? How exactly does it happen that if the strLeft string is interned the expression evaluates to true, otherwise to false? Reference comparison does not explain this behavior. |
Beta Was this translation helpful? Give feedback.
-
Ah, thanks! Now i understand. I wish the (some) documentation for |
Beta Was this translation helpful? Give feedback.
@EgorBo
If that were the case, the three cases i outlined in my report should all evaluate to false (because strLeft and strRight are separate string instances in every of these three cases), no?
How exactly does it happen that if the strLeft string is interned the expression evaluates to true, otherwise to false? Reference comparison does not explain this behavior.