我正在尝试制作如下所示的方法。
它只是添加两个给定的对象并返回。
object add(object a, object b);
我已经使用dynamic
关键字进行了尝试。不幸的是,这不适用于iOS。 (平台不允许生成运行时代码)
dynamic add(dynamic a, dynamic b) => a + b;
所以,这是我的第二次尝试,我意识到用这种方式将是地狱。
private static HybInstance Add(HybInstance a, HybInstance b)
{
if (a.Is<Int32>()) return AddInt32(a, b);
/* and so on... */
}
private static HybInstance AddInt32(HybInstance a, HybInstance b)
{
Int32 ia = a.As<Int32>();
if (b.Is<Int16>()) return HybInstance.Int(ia + b.As<Int32>());
if (b.Is<Int32>()) return HybInstance.Int(ia + b.As<Int32>());
if (b.Is<Int64>()) return HybInstance.Int64(ia + b.As<Int64>());
if (b.Is<float>()) return HybInstance.Float(ia + b.As<float>());
throw new SemanticViolationException($"");
}
// the method should support custom operators too
private static MethodInfo GetAddMethod(HybInstance left) {
return left.GetMethods("op_Addition").FirstOrDefault();
}
有没有更聪明的方法来添加两个对象?
添加:
这是我想做的一些例子。 只需添加任何类型的对象,否则将引发异常。
add(1, 1); // 2
add(1, "b"); // exception
add("a", "b"); // "ab"
// and this one also should be work
add(some_class_with_operator_overloading, 10);
答案 0 :(得分:2)
使用标准.NET类型可能获得的最接近的结果是IConvertible
:
static IConvertible Add (IConvertible a, IConvertible b)
{
if (a is string) return a.ToString() + b;
if (b is string) return a + b.ToString();
// other special cases here
return a.ToDouble(CultureInfo.CurrentCulture) + b.ToDouble(CultureInfo.CurrentCulture);
}
static void Main(string[] args)
{
IConvertible a = 1;
IConvertible b = 2;
IConvertible s = "string";
Console.WriteLine(Add(a, b));
Console.WriteLine(Add(s, s));
Console.WriteLine(Add(a, s));
}
生产
3
stringstring
1string
答案 1 :(得分:0)
不可能添加两个对象,因为关于可以添加的对象没有任何内容。
这就像您要在“某物”上添加“某物”,并希望某人用准确的答案回答您的问题-这是不可能的。
object
没有任何字段或属性,因此您想如何添加它们?
除非您牢记某种基于真实类型添加object
的一般规则,否则这将成为可能:您将必须检查输入参数的类型,然后(相当)庞大switch
语句返回适当的结果(例如,字符串连接,整数简单加法...)。
答案 2 :(得分:0)
Refelction可用于遍历两个对象的属性,检查名称的等效性和数字数据类型,然后以完全通用的方式修改属性值:
public static void AddObjects(object oFrom, object oTo)
{
if (oFrom != null && oTo != null)
{
foreach (System.Reflection.PropertyInfo f in oFrom.GetType().GetProperties())
{
if ((oTo).GetType().GetProperty(f.Name) != null)
{
try
{
string sType = f.GetType().ToString().ToLower();
if (sType==("int") )
{
oFrom.GetType().GetProperty(f.Name).SetValue(oFrom, (int)(f.GetValue(oFrom)) + (int)(f.GetValue(oTo)));
}
if (sType=="int32" )
{
oFrom.GetType().GetProperty(f.Name).SetValue(oFrom, (Int32)(f.GetValue(oFrom)) + (Int32)(f.GetValue(oTo)));
}
if (sType==("int64") )
{
oFrom.GetType().GetProperty(f.Name).SetValue(oFrom, (Int64)(f.GetValue(oFrom)) + (Int64)(f.GetValue(oTo)));
}
// keep adding for all numeirc types. maybe theres a better way?
}
catch (Exception ex)
{ }
}
}
}
}
答案 3 :(得分:0)
更新
似乎也不行
没有动态代码生成
由于iOS内核阻止应用程序动态生成代码,因此Xamarin.iOS不支持任何形式的动态代码生成。这些包括:
但是
Why does LambdaExpression.Compile() work on iOS (Xamarin)?
在支持代码生成的平台上,基于Reflection.Emit
LambdaCompiler
使用。如果该选项不可用,则使用解释 口译员 例如,有些类解释
Constant
和Add
。
原始
我不确定您可以从中得到多少里程,但是您可以使用表达式
public static object Add<T,T2>(T a,T2 b)
{
var paramA = Expression.Parameter(typeof(T), "a");
var paramB = Expression.Parameter(typeof(T2), "b");
var body = Expression.Add(Expression.Convert(paramA, paramB.Type), paramB);
var add = Expression.Lambda<Func<T, T2, T2>>(body, paramA, paramB).Compile();
return add(a, b);
}
假设它将尝试转换为第二个参数类型并返回该类型。
很显然,任何课程都需要适当的运算符
给出
public struct Test
{
// user-defined conversion from Fraction to double
public static implicit operator int(Test f)
{
return 10;
}
public static implicit operator Test(int i)
{
return new Test();
}
// overload operator *
public static Test operator +(Test a, Test b)
{
return new Test();
}
}
示例
Console.WriteLine(Add(1, 2));
Console.WriteLine(Add(1, 2.0));
Console.WriteLine(Add(1, new Test()));
答案 4 :(得分:0)
您尝试使用泛型,但是有两件事:
我将拥有一个泛型函数,并向其传递可以为不同类型定义的Add / Combine函数。似乎是一种更清洁的方法。
Parallelism : sequential/Dc_aware