开发者

C# Custom Type Declaration - Not Working

开发者 https://www.devze.com 2023-03-25 17:27 出处:网络
G\'Day, Apologies for the length of the post, however the code is necessary. I would like to create my own value types in C#. I have implemented a struct TCountryID but it appears I am still missin

G'Day,

Apologies for the length of the post, however the code is necessary.

I would like to create my own value types in C#. I have implemented a struct TCountryID but it appears I am still missing something as I have the following issues after writing the following code:

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

1) Cannot convert type 'MyNamespace.System.TCountryID' to 'int'

Having implemented the IConvertable interface I would have thought this was dealt with?

2.1) Cannot implicitly convert type 'int' to 'MyNameSpace.System.TCountryID' 2.2) Cannot implicitly convert type 'MyNameSpace.System.TCountryID' to 'int'

How do I achieve a solution to the 2.x issues?

TIA

The struct code is below:

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

            re开发者_C百科turn ((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
    }


No, the C# language doesn't know anything about the IConvertible interface. That only comes into play if you call Convert.ToType or whatever.

If you want to allow conversions to/from int, you'll need to provide them explicitly within your type:

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

Personally I would think hard before doing this though - implicit conversions can make code less readable if you're not careful. (I'd also advise you not to call it TCountryID - the T prefix doesn't follow .NET naming conventions. Using a prefix of F for fields is pretty odd too, IMO.)


From the documentation: "The common language runtime typically exposes the IConvertible interface through the Convert class. The common language runtime also uses the IConvertible interface internally, in explicit interface implementations, to simplify the code used to support conversions in the Convert class and basic common language runtime types".

So you will still need to call Convert. For example:

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

精彩评论

暂无评论...
验证码 换一张
取 消