• 通过自定义字符串内插处理程序(InterpolatedStringHandler)和CallerArgumentExpression特性来实现一个好玩的场景


    背景知识介绍

    臆想的一个场景: 拼接字符串, 要求自动包含字符串变量的名字和值, 并用":,"分割.

    PS:仅仅是为了探索这2个特性的用法, 编码规范和实用性不在考虑范围内

    • input: 有参数 [a,b,c]
    • output "a:{a}, b:{b}, c:{c}"; {}中表示该参数的值.

    利用字符串内插的方式实现这个场景

    定义一个F方法并通过字符串内插传入需要拼接的参数, 如F($"{a}{b}{c}")

    实现自定义的字符串内插处理程序

    [InterpolatedStringHandler]
    public ref struct MyInterpolatedStringHandler
    {
        DefaultInterpolatedStringHandler _default;
        bool firstAppend = false;
        public MyInterpolatedStringHandler(int literalLength, int formattedCount)
        {
            _default = new DefaultInterpolatedStringHandler(literalLength + (formattedCount * 16), formattedCount);
            // 在DefaultInterpolatedStringHandler 内部初始化char buffer 大小用的计算方法是: literalLength + formattedCount*11
            // 所以我们假定我们的单个参数表达式的长度是13, 然后在加固定的3个字符" , :" 一共16个字符. 所以有了(formattedCount * 16)
            // 当然, 我们可以在这里吧要写入的对象传入进来(利用InterpolatedStringHandlerArgument特性), 比如说官方例子里面的Logger对象.
            // 参考 https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/tutorials/interpolated-string-handler#add-more-capabilities-to-the-handler
        }
        public void AppendLiteral(string s)
        {
            _default.AppendLiteral(s); // AppendLiteral处理内插字符串中的字面量, 意思就是 `$"aa:{a}"` 中的 `aa:`是字面量
        }
        public void AppendFormatted<T>(T t, [CallerArgumentExpression("t")] string? tName = null)
        {
            // 按照我们想要的格式拼接字符串.
            if (!append) _default.AppendLiteral(", ");
            firstAppend = true;
            _default.AppendLiteral(tName);
            _default.AppendLiteral(":");
            _default.AppendFormatted(t);
        }
        public string ToStringAndClear()
        {
            var s = _default.ToStringAndClear();
            this = default;
            return s;
        }
    }
    

    实现F方法

    void F(MyInterpolatedStringHandler s)=> Console.WriteLine(s.ToStringAndClear());
    

    调用例子

    int a=0;
    int b=1;
    string c=2;
    F($"{a}{b}{c}") //output "a:0, b:1, c:2"
    

    如果我们反编译这些代码,会看到和下面代码差不多:

    public void Main()
    {
        int a=0;
        int b=1;
        string c=2;
        
        MyInterpolatedStringHandler result = new MyInterpolatedStringHandler(0, 3);
        result.AppendFormatted(a, "a");
        result.AppendFormatted(b, "b");
        result.AppendFormatted(c, "c");
        
        F(result);
    }
    

    总结

    • 这2个特性的更多介绍可以参考上面背景知识中给出的连接. 官方介绍很详细
    • 什么场景下适合自定义一个字符串内插程序(string interpolation handler) 可以阅读 新大纲
  • 相关阅读:
    转盘抽奖活动代码
    信息滚动条
    gulp应用学习
    js实现语音播报功能
    如何安装使用sass
    纯CSS写三角形-border法
    css兼容性写法
    字体中英文对照
    浏览器内核判断
    个人课程总结
  • 原文地址:https://www.cnblogs.com/calvinK/p/15937391.html
Copyright © 2020-2023  润新知