Я пытаюсь сделать какой-то метод, как показано ниже.
Он просто добавляет два заданных объекта и возвращает.
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);
IConvertible
использованию стандартных типов .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
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)
{ }
}
}
}
}
int
и int32
- это одно и то же. Не то, чтобы я пошел с этим подходом, но почему все сравнения строк? Type type = f.GetType(); if(type == typeof(int)) { ... }
или, возможно, даже лучше (если c # 7+) использовать switch
сопоставления с образцом
Вы пробовали с дженериками, хотя 2 вещи:
У меня была бы универсальная функция, и я бы передал ей функцию Add/Combine, которая может быть определена для разных типов. Кажется, более чистый подход.
public T Add<T1, T2, T>(T1 firstObject, T2 secondObject, Func<T1,T2,T>Combine)
{
var result = Combine(firstObject, secondObject);
return result;
}
Combine
Невозможно добавить два объекта, потому что нет ничего об объектах, которые можно добавить.
Это как если бы вы хотели добавить "что-то" к "чему-то" и ожидали, что кто-то ответит на ваш вопрос точным ответом - это невозможно.
object
нет полей или свойств, так как бы вы хотели их добавить?
Если вы не имеете в виду какое-то общее правило добавления object
основанное на их реальном типе, тогда это станет возможным: вам придется проверять тип входных параметров, а затем в (скорее) огромном операторе switch
возвращать соответствующий результат (например, конкатенация для строк, простое сложение для целых чисел...).
dynamic
) делает именно то, что я хочу.
Обновить
Похоже, это тоже не сработает
Нет динамической генерации кода
Поскольку ядро iOS не позволяет приложению динамически генерировать код, Xamarin.iOS не поддерживает какую-либо форму динамического генерирования кода. Они включают:
тем не мение
Почему LambdaExpression.Compile() работает на iOS (Xamarin)?
На платформах, которые поддерживают генерацию кода, используется
LambdaCompiler
основе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()));