Пользовательское объявление типа C # - не работает - PullRequest
0 голосов
/ 03 августа 2011

G'Day,

Извиняюсь за длину поста, однако код необходим.

Я хотел бы создать свои собственные типы значений в C #.Я реализовал struct TCountryID, но, похоже, я все еще что-то упустил, поскольку у меня возникли следующие проблемы после написания следующего кода:

    int iTest = 0;
    TCountryID tcidTest;
    iTest = tcidTest;

1) Невозможно преобразовать тип 'MyNamespace.System.TCountryID' в 'int'

Реализовав интерфейс IConvertable, я бы подумал, что с этим справились?

2.1) Не удалось неявно преобразовать тип' int 'в' MyNameSpace.System.TCountryID '2.2) Не удалось неявно преобразовать типОт 'MyNameSpace.System.TCountryID' до 'int'

Как мне решить проблему с 2.x?

TIA

Код структуры приведен ниже:

    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public struct TCountryID : IFormattable, IConvertible, IComparable, IComparable<TCountryID>, IEquatable<TCountryID>
    {
        #region Private Members
        private int FValue;                      //Base type we are encapsulating
        #endregion

        #region Public Members

        public override int GetHashCode()
        {
            return FValue;
        }

        #region IConvertible
        public TypeCode GetTypeCode()
        {
            return TypeCode.Int32;
        }

        bool IConvertible.ToBoolean(IFormatProvider AProvider)
        {
            return System.Convert.ToBoolean(FValue);
        }

        byte IConvertible.ToByte(IFormatProvider AProvider)
        {
            return System.Convert.ToByte(FValue);
        }

        char IConvertible.ToChar(IFormatProvider AProvider)
        {
            return Convert.ToChar(FValue);
        }

        DateTime IConvertible.ToDateTime(IFormatProvider AProvider)
        {
            return System.Convert.ToDateTime(FValue);
        }

        decimal IConvertible.ToDecimal(IFormatProvider AProvider)
        {
            return System.Convert.ToDecimal(FValue);
        }

        double IConvertible.ToDouble(IFormatProvider AProvider)
        {
            return System.Convert.ToDouble(FValue);
        }

        short IConvertible.ToInt16(IFormatProvider AProvider)
        {
            return System.Convert.ToInt16(FValue);
        }

        int IConvertible.ToInt32(IFormatProvider AProvider)
        {
            return System.Convert.ToInt32(FValue) ;
        }

        long IConvertible.ToInt64(IFormatProvider AProvider)
        {
            return System.Convert.ToInt64(FValue);
        }

        sbyte IConvertible.ToSByte(IFormatProvider AProvider)
        {
            return System.Convert.ToSByte(FValue);
        }

        float IConvertible.ToSingle(IFormatProvider AProvider)
        {
            return System.Convert.ToSingle(FValue);
        }

        object IConvertible.ToType(Type ATargetType, IFormatProvider AProvider)
        {
            if (ATargetType == null)
                throw new ArgumentNullException("ATargetType");

            return System.Convert.ChangeType(FValue, ATargetType, AProvider);
        }

        ushort IConvertible.ToUInt16(IFormatProvider AProvider)
        {
            return System.Convert.ToUInt16(FValue);
        }

        uint IConvertible.ToUInt32(IFormatProvider AProvider)
        {
            return System.Convert.ToUInt32(FValue);
        }

        ulong IConvertible.ToUInt64(IFormatProvider AProvider)
        {
            return System.Convert.ToUInt64(FValue);
        }

        #endregion
        #region IComparable
        public int CompareTo(object AValue)
        {
            TCountryID tcidTmp = (TCountryID)AValue;

            if (AValue == null)
                return 1;

            if (!(AValue is System.Int32))
                throw new ArgumentException("Value is not a System.Int32");

            if (FValue == tcidTmp.FValue)
                return 0;

            if (FValue > tcidTmp.FValue)
                return 1;
            else
                return -1;
        }

        public int CompareTo(TCountryID AValue)
        {
            if (FValue == AValue.FValue)
                return 0;

            if (FValue > AValue.FValue)
                return 1;
            else return -1;
        }
#endregion
        #region IEquatable
        public bool Equals(TCountryID obj)
        {
            return obj.FValue == FValue;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is System.TCountryID))
                return false;

            return ((TCountryID)obj).FValue == FValue;
        }
        #endregion
        #region IFormattable
        public override string ToString()
        {
            return FValue.ToString();
        }

        public string ToString(IFormatProvider AProvider)
        {
            return FValue.ToString(AProvider);
        }

        public string ToString(string AFormat)
        {
            return FValue.ToString(AFormat, null);
        }

        public string ToString(string AFormat, IFormatProvider AProvider)
        {
            return FValue.ToString(AFormat, AProvider);
        }
        #endregion
        #endregion
    }

Ответы [ 2 ]

4 голосов
/ 03 августа 2011

Нет, язык C # ничего не знает об интерфейсе IConvertible. Это вступает в игру только тогда, когда вы звоните Convert.ToType или как угодно.

Если вы хотите разрешить преобразования в / из int, вам необходимо явно указать их в вашем типе:

public static implicit operator int(TCountryID id)
{
    return FValue; 
}

public static implicit operator TCountryID(int id)
{
    return new TCountryID(id); // You'll need to create this constructor...
}

Лично я бы подумал, прежде чем делать это - неявные преобразования могут сделать код менее читабельным, если вы не будете осторожны. (Я бы также посоветовал вам , а не называть его TCountryID - префикс T не соответствует соглашениям об именах .NET. Использование префикса F для полей тоже довольно странно, IMO .)

1 голос
/ 03 августа 2011

Из документации: «Среда общего языка обычно предоставляет интерфейс IConvertible через класс Convert. Среда общего языка также использует интерфейс IConvertible внутри, в явных реализациях интерфейса, для упрощения кода, используемого для поддержки преобразований в классе Convertи основные общеязыковые типы времени выполнения ".

Так что вам все равно придется вызывать Convert.Например:

int iTest = 0;
TCountryID tcidTest;
iTest = Convert.ToInt32(tcidTest);
...