在插值字符串内隐式转换为String/string

Rob*_*n B 5 c# string excel string-interpolation implicit-conversion

所以我偶然发现了以下情况:

Console.WriteLine(currentRow["Projekt"]);
Console.WriteLine($"{currentRow["Projekt"]}");
Console.WriteLine($"{(string)currentRow["Projekt"]}");
Run Code Online (Sandbox Code Playgroud)

随着输出:

> Data that i want
> Namespace.ExcelDataField
> Data that i want
Run Code Online (Sandbox Code Playgroud)

ExcelDataField我显然是一个类,我写的是帮助我从excel表中读取数据.我尝试将其实现为与MoveFirst/Next类似的VBA DAO访问,并始终暴露1行数据(currentRow).

我使用ExcelDataField类来封装来自excel表格的数据,因为数据来自excel表格中的dynmic.

public class ExcelDataField<T>
{
    private Excel.Range m_XlRange;
    private int m_Row;
    private int m_Col;

    public T Data
    {
        get
        {
            return (T)(this.m_XlRange.Cells[this.m_Row, this.m_Col] as Excel.Range)?.Value2;
        }

        set
        {
            this.m_XlRange.Cells[this.m_Row, this.m_Col] = value;
        }
    }

    public ExcelDataField(Excel.Range range, int row, int col)
    {
        this.m_XlRange = range;
        this.m_Row = row;
        this.m_Col = col;
    }

    public static implicit operator T(ExcelDataField<T> dataField)
    {
        return dataField.Data;
    }
}
Run Code Online (Sandbox Code Playgroud)

目前我正在考虑测试目的,以后所有数据都可以很容易地作为一个字符串来处理,因为我对这个类进行了重载,这ExcelDataField : ExcelDataField<string>是我用来读取excel表并将其读回控制台的类.

只要我没有使用内插字符串,显然找不到我的隐式转换,一切正常.我试图改变ExcelDataField : ExcelDataField<string> ExcelDataField : ExcelDataField<String>但两个都不起作用.

在我的理解中,插值字符串使用FormattableString类型,该类型没有任何来自string或String的隐式转换只显式.

我的问题是,任何人都可以更详细地解释这里到底发生了什么,是否有一种干净的方式让我能够使用插值字符串?

ang*_*son 6

插入的字符串要么被编译成string.Format(...)表达式,要么被编译成内部使用的包装类FormattableStringstring.Format(...)

以下是为每个此类参数考虑的选项的纲要:

  1. 是否IFormatProviderstring.Format(...)返回ICustomFormatter时问?如果是,则首先咨询ICustomFormatter.Format每个值。
  2. 参数值的类型是否实现IFormattable?如果是,则IFormattable.ToString被称为
  3. 如果没有,则.ToString()直接在值上调用该方法

因此,在您的情况下,您最好的选择可能只是覆盖ToString().

确切的代码(至少在参考源中)在里面StringBuilder,可以在这里找到:StringBuilder.cs, line 1441 - AppendFormatHelper method


Pat*_*man 5

这很容易.$"{currentRow["Projekt"]}"就像是一样的string.Format("{0}", currentRow["Projekt"]).在object提供的实例上currentRow["Projekt"],ToString调用该方法.默认实现object是它返回类型名称.

所以你基本上所要做的就是覆盖那种行为.你可以通过覆盖ToString方法来做到这一点:

public override string ToString()
{
    return dataField.Data?.ToString();
}
Run Code Online (Sandbox Code Playgroud)