简体   繁体   中英

Implicit conversion to String/string inside interpolated string

So I stumbled upon the following:

Console.WriteLine(currentRow["Projekt"]);
Console.WriteLine($"{currentRow["Projekt"]}");
Console.WriteLine($"{(string)currentRow["Projekt"]}");

With the output:

> Data that i want
> Namespace.ExcelDataField
> Data that i want

Where ExcelDataField i obviously a class I wrote to help me read data out of an excel sheet. I tried to implement this to resemble VBAs DAO access with MoveFirst/Next and always expose 1 row of data (currentRow).

I used a class ExcelDataField to encapsulate the data coming out of my excel sheet as the data comes as dynmic out of the excel sheet.

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;
    }
}

Currently I am asuming for testing purposes that all data can later easily be handled as a string to I made an overload of this class ExcelDataField : ExcelDataField<string> which is the class I am using to read an excel sheet into and just reading it back to console.

Everything works fine as long as I am not using interpolated strings which obviously don't find my implicit conversion. I tried to change ExcelDataField : ExcelDataField<string > to ExcelDataField : ExcelDataField<String> but both don't work.

In my understanding interpolated strings use the FormattableString type which doesn't have any implicit conversion from string or String only explicit.

My question would be can anyone explain in greater detail what exactly is going on here and is there a clean way for me to able to use interpolated strings?

It is fairly easy. $"{currentRow["Projekt"]}" is just the same as string.Format("{0}", currentRow["Projekt"]) . On the object instance provided by currentRow["Projekt"] , the ToString method is called. The default implementation on object is that it returns the type name.

So basically all you have to do is to override that behavior. You can do that by overriding the ToString method:

public override string ToString()
{
    return dataField.Data?.ToString();
}

Interpolated strings will either be compiled into a string.Format(...) expression, or compiled into a wrapper class FormattableString that internally uses string.Format(...)

Here's a rundown of the options considered for each such parameter:

  1. Does the IFormatProvider given to string.Format(...) return a ICustomFormatter when asked? If yes then consult ICustomFormatter.Format for each value first.
  2. Does the type of the parameter value implement IFormattable ? If yes, then IFormattable.ToString is called
  3. If no, then the .ToString() method is called directly on the value

So in your case, your best option is probably to just override ToString() .

The exact code (at least in reference source) is inside StringBuilder , found here: StringBuilder.cs, line 1441 - AppendFormatHelper method .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM