Индексатор явно реализовал IFormattable

Я написал себе индексатор, он работает, но как только я реализую явное «IFormatable», он больше не работает.

Почему это не работает и как использовать его явно?

Вот что я пробовал:

/// <summary>
/// Example of Coordinates for 3 dimensions.
/// </summary>
public class Coordinates:IFormattable
{
    #region Constructor
    public Coordinates(int x, int y, int z)
    {
        _x = x;
        _y = y;
        _z = z;
        _length = 3;
    }
    #endregion
    #region IFormattable implemented
    /// <summary>
    /// Formating custom string
    /// </summary>
    /// <param name="format">Format("A"-all value,...,"H"-)</param>
    /// <param name="formatProvider">Different culture</param>
    /// <returns></returns>
    public string IFormattable.ToString(string format, IFormatProvider formatProvider)
    {
        if (format==null)
        {
            return ToString(); //Fallbasck
        }
        else
        {
            switch (format.ToUpper())//gross, kleinschreibung egal
            {
                case "A": return ToString();
                case "X": return _x.ToString();
                case "Y": return _y.ToString();
                case "Z": return _z.ToString();
                case "H": return String.Format("{0:h}", ToString());
                default:
                    throw new FormatException(String.Format("Format {0} is not defined.", format));
            }
        }
    }

    public string ToString(string format)
    {
        return ToString(format, null); //Error occurs here
    }

    #endregion
    #region overWriteToString
    /// <summary>
    /// will be called implicit
    /// </summary>
    /// <returns>[x,y,z]</returns>
    public override string ToString()
    {
        return String.Format("[{0},{1},{2}]",_x,_y,_z);
    }
    #endregion
    #region Properties
    private int _x;

    public int X
    {
        get { return _x; }
        set { _x = value; }
    }

    private int _y;

    public int Y
    {
        get { return _y; }
        set { _y = value; }
    }

    private int _z;

    public int Z
    {
        get { return _z; }
        set { _z = value; }
    }

    private int _length;

    public int Length
    {
        get { return _length; }
    }

    #endregion
    #region Indexer
    /// <summary>
    /// My own indexer for x,y,z
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    public int this[int val]
    {
        get
        {

            switch (val)
            {
                case 0: return _x; ;
                case 1: return _y; ;
                case 2: return _z; ;
                default:
                    throw new IndexOutOfRangeException("Indexer not avaiable.");
            }

        }
        //kann auch setter haben
    }

    #endregion

}

Подробно изучаю C#.

Ошибка возникает здесь:

public string ToString(string format)
{
    return ToString(format, null); //Error occurs here
}

person user254197    schedule 07.08.2015    source источник
comment
Я знаю, что прошло некоторое время, но если вы используете свойства с резервными полями только для public int Z { get { return _z; } set { _z = value; } } возвращаемых значений, используйте автосвойства, такие как public int Z {get; set;}   -  person Mafii    schedule 17.03.2016


Ответы (1)


Реализуя ToString(string format, IFormatProvider formatProvider) явно, вы можете вызывать его только через ссылку с типом времени компиляции IFormattable.

Вы можете сделать это, используя this:

return ((IFormattable)this).ToString(format, null);

Or:

IFormattable formattable = this;
return formattable.ToString(format, null);

Я бы, вероятно, добавил комментарий к коду, объясняющий, почему вы выполняете приведение типов, так как это не очевидно, пока вы не заметите, что метод явно реализует IFormattable.ToString.

Кстати, есть ли причина, по которой вы хотите реализовать это явно? Это похоже на то, что должно быть доступно — и вы должны использовать переданный IFormatProvider.

person Jon Skeet    schedule 07.08.2015
comment
Я сделал это только явно, чтобы я мог видеть, откуда приходит ToString(...), я знаю, что на самом деле явная реализация изобретена, если у вас есть другой интерфейс с одним и тем же методом, но я не мог придумать другой подход к сделанному ясно, откуда берется ToString(...) - person user254197; 07.08.2015
comment
@user254197: user254197: Что вы имеете в виду под тем, откуда приходит ToString? - person Jon Skeet; 07.08.2015
comment
У меня есть 3 ToString()-метода, и я хотел бы видеть, что один исходит из интерфейса IFormattable.ToString(...), чтобы всем было ясно, какие из них (toString()) мои, а какие из них основаны на .Net. - person user254197; 07.08.2015
comment
@user254197: Почему это кого-то волнует? Вы можете документировать, какой из них реализует интерфейс, но использование явной реализации интерфейса только усложняет его использование в другом месте... - person Jon Skeet; 07.08.2015
comment
Вы правы, хотя, если я сделаю это так, как прежде, вы увидите это с первого взгляда... - person user254197; 07.08.2015