首页 > 解决方案 > 字符串运算符 + 源代码在哪里?

问题描述

当我检查以下代码是否string s = "a" + 1有效时。

在工具提示中,Visual Studio 显示它使用string operator + (string left, object right)在此处输入图像描述

无论如何,它在String 的源代码中没有提到,因为只有==and !=

我绝对可以假设它使用类似于 的东西left + right.ToString(),但真的想检查它的真实源代码。

PS 在 C# 源代码中不存在它使我对无限的兴趣倍增:)

标签: c#.net

解决方案


这对我来说是新的,我不是编译器专家,这是我最好的选择。

源代码在哪里?

简短的回答

贯穿.NET Compiler Platform ("Roslyn")的代码。

更长的答案

c# 中有 3 个内置运算符 for string.

string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);

(参考下文)

BuiltInOperators您可以在 Roslyn 的课堂源代码中看到它们。

(int)BinaryOperatorKind.StringConcatenation,
(int)BinaryOperatorKind.StringAndObjectConcatenation,
(int)BinaryOperatorKind.ObjectAndStringConcatenation,

您可以按照Kinds 到BinaryOperatorKind枚举。

StringConcatenation = String | Addition,
StringAndObjectConcatenation = StringAndObject | Addition,
ObjectAndStringConcatenation = ObjectAndString | Addition,

调用 string.Concat的魔法的最后部分(在它被识别为加法表达式之后)+似乎发生在RewriteStringConcatenation方法中。

首先将左侧和右侧转换为字符串,这可能需要调用ToString(),您可以在其他人发布的 IL 中看到。

// Convert both sides to a string (calling ToString if necessary)
loweredLeft = ConvertConcatExprToString(syntax, loweredLeft);
loweredRight = ConvertConcatExprToString(syntax, loweredRight);

很多行之后,RewriteStringConcatenationNNNxprs可能会调用其中一个方法,例如RewriteStringConcatenationTwoExprs提供特殊方法的string.Concat方法。

private BoundExpression RewriteStringConcatenationTwoExprs(SyntaxNode syntax, BoundExpression loweredLeft, BoundExpression loweredRight)
{
   Debug.Assert(loweredLeft.HasAnyErrors || loweredLeft.Type.IsStringType());
   Debug.Assert(loweredRight.HasAnyErrors || loweredRight.Type.IsStringType());

   var method = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatStringString);
   Debug.Assert((object)method != null);

   return (BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredLeft, loweredRight);
}

字符串运算符的参考

以下来自表达式文章的加法运算符部分,它是 C# 规范的一部分。

  • 字符串连接:
string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);

二元 + 运算符的这些重载执行字符串连接。如果字符串连接的操作数为 null,则替换为空字符串。否则,通过调用从类型 object 继承的虚拟 ToString 方法,将任何非字符串参数转换为其字符串表示形式。如果 ToString 返回 null,则替换为空字符串。

using System;

class Test
{
    static void Main() {
        string s = null;
        Console.WriteLine("s = >" + s + "<");        // displays s = ><
        int i = 1;
        Console.WriteLine("i = " + i);               // displays i = 1
        float f = 1.2300E+15F;
        Console.WriteLine("f = " + f);               // displays f = 1.23E+15
        decimal d = 2.900m;
        Console.WriteLine("d = " + d);               // displays d = 2.900
    }
}

字符串连接运算符的结果是一个字符串,它由左操作数的字符和右操作数的字符组成。字符串连接运算符从不返回空值。如果没有足够的内存可用于分配结果字符串,则可能会引发 System.OutOfMemoryException。


用于字符串的 .NET 4.8 的源代码在此处,但它仅包含用于operator ==和.NET 的源代码operator !=

语法可视化器

您可能会或可能不会发现这与此问题相关,但 Visual Studio 带有语法可视化器(视图 -> 其他窗口),它为代码生成的一些魔力提供了一个窗口。

在此处输入图像描述


推荐阅读