Top > Programming > .NetFramework > Tips > GetMaxAndMinValueOfValueType
Last-modified: Fri, 09 Aug 2013 23:32:26 JST
Counter:3506 Today:1 Yesterday:0 Online:8
このエントリーをはてなブックマークに追加

値型の最大値と最小値を得る

About

ニッチ需要極まりないですが、ある値が値型か否かを判定して、さらに値型であった場合に、その最大値と最小値を取得する方法について紹介します。

HowTo

サンプルプロジェクトを掲載するほどのものでもないので、コンソールアプリケーションのソースコードをそのまま全文貼り付けます。

まず与えられた型が数値型かどうかを確認します。サンプルでは"IsNumericTypeメソッド"で確認しています。.NetにはIsValueTypeプロパティが実装されていますが、列挙型(Enum)やBoolean/bool型、任意に実装した構造体なども値型であるため、このプロパティでは最大最小値が定義されない型を取り除くことができません。

次にTypeCodeを利用して数値型のいずれかである場合を検出し、その最大値と最小値を取得します。ここで数値型の最大値と最小値はフィールド変数(定数)"MaxValue"と"MinValue"で定義されていることに注目します。フィールドが確かに存在するとき、そのフィールドの情報は"Type.GetFieldメソッド"で取得することができます。さらに与えられている値を取得するとき、"GetValueメソッド"を利用します。本来メソッドの引数にはフィールドの値を取得する対象となるオブジェクト(のインスタンス)を与える必要がありますが、最大値と最小値は定数として定義されているので、ここではnullで良いです。

ここで1点注意する必要があります。C#であつかわれる列挙型(enum)には、値を定義することができる点です。C#ではbyte, sbyte, short, ushort, int, uint, long, ulong型の値を定義することができます。列挙型のTypeCodeを取得するとき、先に挙げた値型の何れかのTypeCodeと同じ値を示します。列挙型は値型と同じTypeCodeを示しますが、最大値と最小値を示すフィールド変数"MaxValue"と"MinValue"を持たないため、不具合が生じます。幸いなことに、列挙型であるかどうかは"Type.IsEnumプロパティ"を利用して判定することができるので、列挙型の場合には、値型でないとすることができます。

    class Program
    {
        enum SampleEnum { a, b, c };

        static void Main(string[] args)
        {
            Type myType = typeof(int);

            if (IsNumericType(myType))
            {
                Console.WriteLine(myType);
                Console.WriteLine((myType.GetField("MaxValue").GetValue(null)));
                Console.WriteLine((myType.GetField("MinValue").GetValue(null)));
                //例えば最大最小値をdoubleに変換するとき
                double value = Convert.ToDouble(myType.GetField("MaxValue").GetValue(null));
            }

            Console.ReadLine();
        }

        public static bool IsNumericType(Type type)
        {
            if (type == null)
                return false;
            if (type.IsValueType == false)
                return false;
            if (type.IsEnum)
                return false;

            TypeCode typeCode = Type.GetTypeCode(type);

            switch (typeCode)
            {
                case TypeCode.Byte:
                case TypeCode.SByte:
                case TypeCode.Char:
                case TypeCode.Decimal:
                case TypeCode.Single://float
                case TypeCode.Double://double
                case TypeCode.Int16://short
                case TypeCode.Int32://int
                case TypeCode.Int64://long
                case TypeCode.UInt16://ushort
                case TypeCode.UInt32://uint
                case TypeCode.UInt64://ulong
                    return true;
            }
            return false;
        }
    }

ここで"int"を指定したときの出力結果は次のようになります。

System.Int32
2147483648
-2147483648