none
似たようなメソッドを一つにまとめられないでしょうか RRS feed

  • 質問

  • WindowsXPでC#2005を使用しています

    以下の2つの似たようなメソッドをオーバーロード、ジェネリックまたはその他方法で一つにまとめられないでしょうか。

     

    public static int TryParseUi(string st)
    {
      int ir;
      if (int.TryParse(st, out ir) == true) { return ir; }
      else { return int.MinValue; }
    }

    public static double TryParseUd(string st)
    {
      double ir;
      if (double.TryParse(st, out ir) == true) { return ir; }
     else { return double.MinValue; }
    }

     

    以上、よろしくお願いいたします

    2008年6月18日 5:50

回答

  • TryParseUi と TryParseUd を TryParse という名前に統一したいのなら、結果を戻り値にするのではなく、引数に out をつければ事足ります。
    さらに、これらをひとつのメソッドにまとめたいのならば、リフレクションを使うことで実現できます。ほかの数値型にも対応できる一般性が高いメソッドになりますが、推奨はできません。


    Code Snippet

    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            {
                int a;
                TryParse("10", out a);
                Console.Out.WriteLine(a);
                TryParse("abc", out a);
                Console.Out.WriteLine(a);
            }
            {
                double a;
                TryParse("10", out a);
                Console.Out.WriteLine(a);
                TryParse("abc", out a);
                Console.Out.WriteLine(a);
            }
        }

        public static void TryParse<T>(string st, out T a) where T : new()
        {
            MethodInfo m = typeof(T).GetMethod("TryParse", new Type[] { typeof(string), typeof(T).MakeByRefType()} );
            object[] parameters = new object[] { st, null };
            a = (bool)m.Invoke(null, parameters) ? (T)parameters[1] : (T)typeof(T).GetField("MinValue").GetValue(null);
        }
    }



    2008年6月18日 7:18
  •  めっぱつ さんからの引用
    WindowsXPでC#2005を使用しています

    以下の2つの似たようなメソッドをオーバーロード、ジェネリックまたはその他方法で一つにまとめられないでしょうか。

     

    似たような話をこちらで書きましたのでご参考までに.

    単にメソッドを同じ名前にしたいだけなら,Kazuya Ujihara さんの言われるように out を使う方法もありますし,こんな方法もあるでしょう.

     

    Code Snippet

    public delegate TResult Func<TArg, TResult>(TArg arg);

    public static TResult TryParse<TResult>(string st, Func<int, TResult> func)
    {
        int ir;
        if (!int.TryParse(st, out ir)) { ir = int.MinValue; }
        return func(ir);
    }
    public static TResult TryParse<TResult>(string st, Func<double, TResult> func)
    {
        double ir;
        if (!double.TryParse(st, out ir)) { ir = double.MinValue; }
        return func(ir);
    }

     

    static void Main(string[] args)
    {
        string str = "39617.711694212965";
        DateTime date = TryParse<DateTime>(
                            str,
                            delegate(double d) { return DateTime.FromOADate(d); }
                        ).AddDays(100.0);
    }

     

    名前をまとめるだけなら,他にも方法はあると思います.

     

    なお,「メンバとして定数 MinValue を持つ全ての型 T に対して」,といった制約は .NET Generics では書けません.この記述をまとめるには,

    • リフレクションを使って動的に解決する
    • コードジェネレータを利用して,単一の生成ルールから必要なオーバーロードを全て事前にコード作成する
    • C++ の template のような,コンパイル時解決の技術で記述する (この場合,他の言語ではそのライブラリを利用できない)

    といった方法が考えられますます.

    2008年6月18日 8:13

すべての返信

  • TryParseUi と TryParseUd を TryParse という名前に統一したいのなら、結果を戻り値にするのではなく、引数に out をつければ事足ります。
    さらに、これらをひとつのメソッドにまとめたいのならば、リフレクションを使うことで実現できます。ほかの数値型にも対応できる一般性が高いメソッドになりますが、推奨はできません。


    Code Snippet

    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            {
                int a;
                TryParse("10", out a);
                Console.Out.WriteLine(a);
                TryParse("abc", out a);
                Console.Out.WriteLine(a);
            }
            {
                double a;
                TryParse("10", out a);
                Console.Out.WriteLine(a);
                TryParse("abc", out a);
                Console.Out.WriteLine(a);
            }
        }

        public static void TryParse<T>(string st, out T a) where T : new()
        {
            MethodInfo m = typeof(T).GetMethod("TryParse", new Type[] { typeof(string), typeof(T).MakeByRefType()} );
            object[] parameters = new object[] { st, null };
            a = (bool)m.Invoke(null, parameters) ? (T)parameters[1] : (T)typeof(T).GetField("MinValue").GetValue(null);
        }
    }



    2008年6月18日 7:18
  •  

    Code Snippet

    public static class Parser {
        private delegate bool TryParse<T>(string arg, out T value);
        private static T ParseOrDefault<T>(string arg, TryParse<T> parser, T defaultValue) {
            T x;
            return parser(arg, out x) ? x : defaultValue;
        }
        public static int ParseInt32(string arg) { return ParseOrDefault(arg, int.TryParse, int.MinValue); }
        public static double ParseDouble(string arg) { return ParseOrDefault(arg, double.TryParse, double.MinValue); }
    }

     

     

    こんなのかしらん?
    2008年6月18日 7:50
  •  めっぱつ さんからの引用
    WindowsXPでC#2005を使用しています

    以下の2つの似たようなメソッドをオーバーロード、ジェネリックまたはその他方法で一つにまとめられないでしょうか。

     

    似たような話をこちらで書きましたのでご参考までに.

    単にメソッドを同じ名前にしたいだけなら,Kazuya Ujihara さんの言われるように out を使う方法もありますし,こんな方法もあるでしょう.

     

    Code Snippet

    public delegate TResult Func<TArg, TResult>(TArg arg);

    public static TResult TryParse<TResult>(string st, Func<int, TResult> func)
    {
        int ir;
        if (!int.TryParse(st, out ir)) { ir = int.MinValue; }
        return func(ir);
    }
    public static TResult TryParse<TResult>(string st, Func<double, TResult> func)
    {
        double ir;
        if (!double.TryParse(st, out ir)) { ir = double.MinValue; }
        return func(ir);
    }

     

    static void Main(string[] args)
    {
        string str = "39617.711694212965";
        DateTime date = TryParse<DateTime>(
                            str,
                            delegate(double d) { return DateTime.FromOADate(d); }
                        ).AddDays(100.0);
    }

     

    名前をまとめるだけなら,他にも方法はあると思います.

     

    なお,「メンバとして定数 MinValue を持つ全ての型 T に対して」,といった制約は .NET Generics では書けません.この記述をまとめるには,

    • リフレクションを使って動的に解決する
    • コードジェネレータを利用して,単一の生成ルールから必要なオーバーロードを全て事前にコード作成する
    • C++ の template のような,コンパイル時解決の技術で記述する (この場合,他の言語ではそのライブラリを利用できない)

    といった方法が考えられますます.

    2008年6月18日 8:13
  • とりあえず考えてみました。

     

    Code Snippet

      public static T TryParseUi<T>(string st) where T : IConvertible
      {
         if (typeof(T) == typeof(Int32))
         {
            Int32 wk32;
            if (Int32.TryParse(st, out wk32) == true) return (T)(IConvertible)wk32; else return (T)(IConvertible)Int32.MinValue;
         }
         else if (typeof(T) == typeof(double))
         {
            Double wkdoble;
            if (Double.TryParse(st, out wkdoble) == true) return (T)(IConvertible)wkdoble; else return (T)(IConvertible)Double.MinValue;
         }
         else
            throw new NotSupportedException();

      } 

     

     

    2008年6月18日 8:57
    モデレータ