方法重载和类型转换
Method overload and type conversion
我有两种C#转换方法:
public int MyConvertToInteger(double x) {
if (x > int.MaxValue) {
return int.MaxValue;
} else if (x < int.MinValue || double.IsNaN(x)) {
return int.MinValue;
} else {
return (int)x;
}
}
public int MyConvertToInteger(string str) {
if (str == null) {
return 0;
}
return str.Length;
}
和一个业务方法,每个参数有两种可能的类型,导致四个重载:
public int IntSum(int x, int y) {
unchecked {
return x+y;
}
}
public int IntSum(int x, string y) {
int iy = MyConvertToInteger(y);
return IntSum(x, iy);
}
public int IntSum(double x, int y) {
int ix = MyConvertToInteger(x);
return IntSum(ix, y);
}
public int IntSum(double x, string y) {
int ix = MyConvertToInteger(x);
return IntSum(ix, y);
}
这很烦人但很实用。但是,如果我要添加具有两种可能类型的第三个参数,我们将有多达八个重载,这在 IMO 看来是不可能的。
我想知道是否有办法以某种方式在方法参数中指定可能的转换,这样我们就不会得到大量的重载? (我对 "solutions" 不感兴趣,它涉及采用更通用类型的参数,例如 "object",然后检查传入的任何类型。)
这不是一个好的做法,但请看一下
void Main()
{
var result = new Summer().Sum("1", 2, 3.0);
}
public class Summer
{
private int Convert<T>(T source)
{
throw new NotSupportedException();
}
private int Convert(int source)
{
return source;
}
private int Convert(string source)
{
return source.Length;
}
private int Convert(double source)
{
return (int)source;
}
public int Sum<T, K>(T i1, K i2)
{
return Convert((dynamic)i1) + Convert((dynamic)i2);
}
public int Sum<T, K, S>(T i1, K i2, S i3)
{
return Convert((dynamic)i1) + Convert((dynamic)i2)+ Convert((dynamic)i3);
}
}
您可以自定义复合类型,例如int或double可以表示为
public class IntOrDouble
{
int i;
double d;
public enum MyType
{
None,
Int,
Double
}
MyType myType;
public IntOrDouble(int i)
{
this.i = i;
myType = MyType.Int;
}
public IntOrDouble(double d)
{
this.d = d;
myType = MyType.Double;
}
public MyType GetReturnType()
{
return myType;
}
public int GetInt()
{
if (!myType.Equals(MyType.Int))
{
throw new Exception("wrong type");
}
return i;
}
public double GetDouble()
{
if (!myType.Equals(MyType.Double))
{
throw new Exception("wrong type");
}
return d;
}
}
但这意味着您必须将方法重写为
public int IntSum(IntOrDouble x, IntOrString y)
编辑通用版(以防重复使用)
public enum MyType
{
None,
T1,
T2
}
public class CompositeType<T1,T2>
{
T1 i;
T2 d;
MyType myType;
public CompositeType(T1 i)
{
this.i = i;
myType = MyType.T1;
}
public CompositeType(T2 d)
{
this.d = d;
myType = MyType.T2;
}
public MyType GetReturnType()
{
return myType;
}
public T1 GetT1()
{
if (!myType.Equals(MyType.T1))
{
throw new Exception("wrong type");
}
return i;
}
public T2 GetT2()
{
if (!myType.Equals(MyType.T2))
{
throw new Exception("wrong type");
}
return d;
}
public object GetValue()
{
switch (myType)
{
case MyType.None:
throw new Exception("wrong type");
case MyType.T1:
return GetT1();
case MyType.T2:
return GetT2();
default:
throw new Exception("wrong type");
}
}
}
用法
public int CompositeConversion<T>(CompositeType<int, T> x)
{
switch (x.GetReturnType())
{
case MyType.None:
throw new Exception("wrong type");
case MyType.T1:
return x.GetT1();
case MyType.T2:
if (typeof(T) == typeof(double))
{
return MyConvertToInteger((double)x.GetValue());
}
if (typeof(T) == typeof(string))
{
return MyConvertToInteger((string)x.GetValue());
}
throw new Exception("wrong type");
default:
throw new Exception("wrong type");
}
}
public int IntSum(CompositeType<int,double> x, CompositeType<int, string> y)
{
return CompositeConversion(x) + CompositeConversion(y);
}
单元测试
int test1 = t.IntSum(3.7, "55.9");
int test2 = t.IntSum(
new CompositeType<int,double>(3.7),
new CompositeType<int,string>("55.9")
); // test1 and test2 are both 7
嗯,
I am wondering if there is a way to somehow specify the possible
conversions in the method argument, so that we don't get this
profusion of overloads?
没有。这在 C# 中是不可能的。
有时必须创建许多重载,尤其是当性能受到威胁时。我见过为一个方法创建 50 个重载的项目。然而,可能的是 运行 来自更通用的更严格的重载,换句话说 Sum(x ,y, z)
重载可以 运行 两个 (x, y)
+ (y, z)
所以没有真正的需要在更通用的重载中编写任何其他逻辑,只是为了重用已经存在的逻辑。
唯一的其他选择是接受 params object[]
并确定我们使用的类型、创建复合类型或使用 dynamic
的 .
我有两种C#转换方法:
public int MyConvertToInteger(double x) {
if (x > int.MaxValue) {
return int.MaxValue;
} else if (x < int.MinValue || double.IsNaN(x)) {
return int.MinValue;
} else {
return (int)x;
}
}
public int MyConvertToInteger(string str) {
if (str == null) {
return 0;
}
return str.Length;
}
和一个业务方法,每个参数有两种可能的类型,导致四个重载:
public int IntSum(int x, int y) {
unchecked {
return x+y;
}
}
public int IntSum(int x, string y) {
int iy = MyConvertToInteger(y);
return IntSum(x, iy);
}
public int IntSum(double x, int y) {
int ix = MyConvertToInteger(x);
return IntSum(ix, y);
}
public int IntSum(double x, string y) {
int ix = MyConvertToInteger(x);
return IntSum(ix, y);
}
这很烦人但很实用。但是,如果我要添加具有两种可能类型的第三个参数,我们将有多达八个重载,这在 IMO 看来是不可能的。
我想知道是否有办法以某种方式在方法参数中指定可能的转换,这样我们就不会得到大量的重载? (我对 "solutions" 不感兴趣,它涉及采用更通用类型的参数,例如 "object",然后检查传入的任何类型。)
这不是一个好的做法,但请看一下
void Main()
{
var result = new Summer().Sum("1", 2, 3.0);
}
public class Summer
{
private int Convert<T>(T source)
{
throw new NotSupportedException();
}
private int Convert(int source)
{
return source;
}
private int Convert(string source)
{
return source.Length;
}
private int Convert(double source)
{
return (int)source;
}
public int Sum<T, K>(T i1, K i2)
{
return Convert((dynamic)i1) + Convert((dynamic)i2);
}
public int Sum<T, K, S>(T i1, K i2, S i3)
{
return Convert((dynamic)i1) + Convert((dynamic)i2)+ Convert((dynamic)i3);
}
}
您可以自定义复合类型,例如int或double可以表示为
public class IntOrDouble
{
int i;
double d;
public enum MyType
{
None,
Int,
Double
}
MyType myType;
public IntOrDouble(int i)
{
this.i = i;
myType = MyType.Int;
}
public IntOrDouble(double d)
{
this.d = d;
myType = MyType.Double;
}
public MyType GetReturnType()
{
return myType;
}
public int GetInt()
{
if (!myType.Equals(MyType.Int))
{
throw new Exception("wrong type");
}
return i;
}
public double GetDouble()
{
if (!myType.Equals(MyType.Double))
{
throw new Exception("wrong type");
}
return d;
}
}
但这意味着您必须将方法重写为
public int IntSum(IntOrDouble x, IntOrString y)
编辑通用版(以防重复使用)
public enum MyType
{
None,
T1,
T2
}
public class CompositeType<T1,T2>
{
T1 i;
T2 d;
MyType myType;
public CompositeType(T1 i)
{
this.i = i;
myType = MyType.T1;
}
public CompositeType(T2 d)
{
this.d = d;
myType = MyType.T2;
}
public MyType GetReturnType()
{
return myType;
}
public T1 GetT1()
{
if (!myType.Equals(MyType.T1))
{
throw new Exception("wrong type");
}
return i;
}
public T2 GetT2()
{
if (!myType.Equals(MyType.T2))
{
throw new Exception("wrong type");
}
return d;
}
public object GetValue()
{
switch (myType)
{
case MyType.None:
throw new Exception("wrong type");
case MyType.T1:
return GetT1();
case MyType.T2:
return GetT2();
default:
throw new Exception("wrong type");
}
}
}
用法
public int CompositeConversion<T>(CompositeType<int, T> x)
{
switch (x.GetReturnType())
{
case MyType.None:
throw new Exception("wrong type");
case MyType.T1:
return x.GetT1();
case MyType.T2:
if (typeof(T) == typeof(double))
{
return MyConvertToInteger((double)x.GetValue());
}
if (typeof(T) == typeof(string))
{
return MyConvertToInteger((string)x.GetValue());
}
throw new Exception("wrong type");
default:
throw new Exception("wrong type");
}
}
public int IntSum(CompositeType<int,double> x, CompositeType<int, string> y)
{
return CompositeConversion(x) + CompositeConversion(y);
}
单元测试
int test1 = t.IntSum(3.7, "55.9");
int test2 = t.IntSum(
new CompositeType<int,double>(3.7),
new CompositeType<int,string>("55.9")
); // test1 and test2 are both 7
嗯,
I am wondering if there is a way to somehow specify the possible conversions in the method argument, so that we don't get this profusion of overloads?
没有。这在 C# 中是不可能的。
有时必须创建许多重载,尤其是当性能受到威胁时。我见过为一个方法创建 50 个重载的项目。然而,可能的是 运行 来自更通用的更严格的重载,换句话说 Sum(x ,y, z)
重载可以 运行 两个 (x, y)
+ (y, z)
所以没有真正的需要在更通用的重载中编写任何其他逻辑,只是为了重用已经存在的逻辑。
唯一的其他选择是接受 params object[]
并确定我们使用的类型、创建复合类型或使用 dynamic
的 .