トップ回答者
似たようなメソッドを一つにまとめられないでしょうか

質問
-
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; }
}以上、よろしくお願いいたします
回答
-
TryParseUi と TryParseUd を TryParse という名前に統一したいのなら、結果を戻り値にするのではなく、引数に out をつければ事足ります。
さらに、これらをひとつのメソッドにまとめたいのならば、リフレクションを使うことで実現できます。ほかの数値型にも対応できる一般性が高いメソッドになりますが、推奨はできません。
Code Snippetusing 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);
}
} -
めっぱつ さんからの引用 WindowsXPでC#2005を使用しています 以下の2つの似たようなメソッドをオーバーロード、ジェネリックまたはその他方法で一つにまとめられないでしょうか。
似たような話をこちらで書きましたのでご参考までに.
単にメソッドを同じ名前にしたいだけなら,Kazuya Ujihara さんの言われるように out を使う方法もありますし,こんな方法もあるでしょう.
Code Snippetpublic 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 のような,コンパイル時解決の技術で記述する (この場合,他の言語ではそのライブラリを利用できない)
といった方法が考えられますます.
すべての返信
-
TryParseUi と TryParseUd を TryParse という名前に統一したいのなら、結果を戻り値にするのではなく、引数に out をつければ事足ります。
さらに、これらをひとつのメソッドにまとめたいのならば、リフレクションを使うことで実現できます。ほかの数値型にも対応できる一般性が高いメソッドになりますが、推奨はできません。
Code Snippetusing 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);
}
} -
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); }
} -
めっぱつ さんからの引用 WindowsXPでC#2005を使用しています 以下の2つの似たようなメソッドをオーバーロード、ジェネリックまたはその他方法で一つにまとめられないでしょうか。
似たような話をこちらで書きましたのでご参考までに.
単にメソッドを同じ名前にしたいだけなら,Kazuya Ujihara さんの言われるように out を使う方法もありますし,こんな方法もあるでしょう.
Code Snippetpublic 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 のような,コンパイル時解決の技術で記述する (この場合,他の言語ではそのライブラリを利用できない)
といった方法が考えられますます.
-
とりあえず考えてみました。
Code Snippetpublic 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();}