Примечание. Это функция класса PradResult.
Код: Выделить всё
///
/// Applies the specified IOperation to this PradResult.
///
/// The type of the operation to apply.
///
The first parameter for the operation.
/// The second parameter for the operation.
/// Additional parameters for the operation.
/// A new PradResult after applying the operation.
public PradResult Then(T.Args[0] p1, T.Args[1] p2, params object[] parameters)
where T : IPradOperation, new()
{
var opType = typeof(T);
IOperation op = (IOperation)Activator.CreateInstance(opType);
var forwardMethod = opType.GetMethod("Forward");
var forwardParams = parameters.Prepend(p2).Prepend(p1);
var length = parameters.Length;
...
}
Однако я понимаю, что C# в настоящее время не поддерживает этот синтаксис напрямую. Существуют ли какие-либо обходные пути или альтернативные шаблоны, которые я могу использовать для достижения такого рода вывода типа во время компиляции в моем универсальном методе?
Я хочу, чтобы метод then был максимально удобным для пользователя, поэтому что им не нужно указывать типы «T.Args[0]» и «T.Args[1]», которые в моем примере будут иметь тип «Matrix».
Для полноты картины, вот интерфейс IPradOperation:
Код: Выделить всё
///
/// A PRAD Operation.
///
/// The first parameter to the forward function.
/// The return type of the forward function.
public interface IPradOperation
{
}
Код: Выделить всё
public class AmplifiedSigmoidOperation : Operation, IPradOperation
{
...
///
/// The forward pass of the operation.
///
///
The input for the operation.
/// The output for the operation.
public Matrix Forward(Matrix input)
{
this.input = input;
int numRows = input.Length;
int numCols = input[0].Length;
this.Output = new Matrix(numRows, numCols);
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numCols; j++)
{
this.Output[i][j] = 1.0f / (1.0f + PradMath.Pow(PradMath.PI - 2, -input[i][j]));
}
}
return this.Output;
}
...
}
Код: Выделить всё
[Fact]
public void TestThenGeneric()
{
Tensor tensor = new Tensor(new int[] { 200, 300, 400 }, 5f);
PradOp op = new PradOp(tensor);
Matrix m1 = new Matrix(1, 4);
Matrix m2 = new Matrix(2, 3);
// This would work because AmplifiedSigmoidOperation
// implements IPradOperation
op.SeedResult
.Then(m1, m2, tensor, 1)
.Then(m1, m2); // etc.
}
Чтобы ответить на комментарий:
Я понимаю, что этот сценарий не будет работать, если у вас есть: class AmplifiedSigmoidOperation : Operation, IPradOperation, IPradOperation.
Я бы предположил, что компилятор не позволит вам использовать T.Args[0] и T.Args[1], если бы они были неоднозначными. Но в случаях, когда у вас нет двусмысленности, это будет работать и быть более кратким для пользователя библиотеки.
Кроме того, теоретически возможность сократить двусмысленность может быть чем-то вроде нравится:
Код: Выделить всё
public PradResult Then(T.Args[0] p1, T.Args[1] p2, params object[] parameters)
where T : IPradOperation, new()
Код: Выделить всё
public PradResult Then(T.Args[0] p1, T.Args[1] p2, params object[] parameters)
where T : IPradOperation, new()
where A1 : class
where A2 : class
По духу это похоже на то, как В C# были включены такие функции, как деконструкция кортежей или сопоставление с образцом, которые повышают выразительность и безопасность типов.
Подробнее здесь: https://stackoverflow.com/questions/787 ... orkarounds