Приведение параметра типа к базовому типу без упаковки
Есть ли способ сделать код вроде этой работы:
public class Func2<A, B>
{
private Func<A, B> f;
public Func2(Func<A, B> f)
{
this.f = f;
}
public object invoke(object obj, long l)
{
if (typeof(B) == typeof(long))
{
if (obj != null)
l = (long)obj;
return f((B)l); //error! cannot convert type 'long' to 'B'
} else {
return f((B)obj);
}
}
}
Проблема здесь в том, что я не могу напрямую привести B к long без приведения B к объекту первым. Я стараюсь любой ценой избавиться от необходимости упаковывать данные, так как это значительно замедлит быстрые операции с функциями. Так есть ли способ добиться этого?
Я знаю, что мог бы на самом деле определить специализированный Func2, чтобы конкретно обрабатывать случай, когда B длинная. Но по мере роста арности функции комбинация длинных и объектов растет экспоненциально - и в реальном случае использования я хочу также поддерживать двойные значения! Есть ли способ поддержать это без бокса? Может быть, с небезопасным кодом?
Спасибо! Cauê
2 ответа
Вы можете перегрузить метод, и вместо long
значение для A
Вы можете привести делегата к Func<long, B>
:
public class Func2<A, B> {
private Func<A, B> f;
public Func2(Func<A, B> f) {
this.f = f;
}
public B invoke(long a) {
if (typeof(A) == typeof(long)) {
return (f as Func<long, B>)(a);
} else {
throw new NotSupportedException();
}
}
public B invoke(object a) {
return f((A)a);
}
}
Пример:
Func2<long, string> f = new Func2<long, string>(l => l.ToString());
Console.WriteLine(f.invoke(42)); // calls the invoke(long) method
Console.WriteLine(f.invoke("x")); // calls the invoke(object) method
Только что узнал ответ!:)
public object invoke(object obj, long l)
{
if (typeof(B) == typeof(long))
{
if (obj != null)
l = (long)obj;
Func<A, long> x = (Func<A, long>)(object)f;
return x(l);
} else {
return f((B)obj);
}
}
Таким образом, нам не нужно автоматически вставлять long в объект, но мы фактически приводим тип Func для получения указанного нами long!
Что касается того, почему я пытаюсь это сделать, прочитайте приведенный выше комментарий, и я все равно буду пытаться найти лучший способ сделать это.
К настоящему времени у нас есть следующий haXe-код:
var f:Int->Int->Float = function(x:Int, y:Int) return x + y + 0.5;
var f2:Dynamic->Dynamic->Dynamic = f; // ok
var f3:Dynamic->Int->Dynamic = f; //also ok
f2(10, 30); // ok - this will box the 10 and 30
То, что я пытаюсь сделать, - это создать тип Fun3, который имеет вызов invoke, который будет принимать как коробочные, так и незаписанные аргументы. Если базовая функция действительно принимает распакованные типы, она сначала попытается использовать их.
Спасибо!!