添加两个对象的巧妙方法

时间:2019-04-10 05:40:12

标签: c# .net system.reflection

我正在尝试制作如下所示的方法。
它只是添加两个给定的对象并返回。

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);

5 个答案:

答案 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)

更新

似乎也不行

Limitations of Xamarin.iOS

没有动态代码生成

由于iOS内核阻止应用程序动态生成代码,因此Xamarin.iOS不支持任何形式的动态代码生成。这些包括:

  • System.Reflection.Emit不可用。
  • 不支持System.Runtime.Remoting。
  • 不支持动态创建类型(不支持Type.GetType(“ MyType`1”)),尽管查找现有类型(例如,使用Type.GetType(“ System.String”)也可以)。 反向回调必须在运行时通过编译ti
  • 注册。

但是

Why does LambdaExpression.Compile() work on iOS (Xamarin)?

  

在支持代码生成的平台上,基于Reflection.Emit   LambdaCompiler   使用。

     

如果该选项不可用,则使用解释   口译员    例如,有些类解释ConstantAdd

原始

我不确定您可以从中得到多少里程,但是您可以使用表达式

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)

您尝试使用泛型,但是有两件事:

  1. 您将不同的对象包装在同一个包装器中,这似乎是一个设计问题,但由于我不了解更多,所以将其保留。
  2. 大多数int可以直接更改为Int64,这样就不会有很多特殊情况

我将拥有一个泛型函数,并向其传递可以为不同类型定义的Add / Combine函数。似乎是一种更清洁的方法。

Parallelism : sequential/Dc_aware