Я хочу добавить интерфейс к некоторым встроенным типам. У меня есть интерфейс IConcludable
, который я использую в качестве ограничения для Conclusion<T>
. Я не знаю, как подойти к этому, или если это даже возможно.
Основной макет
public interface IConcludable { }
public struct Conclusion<T> where T : IConcludable
{
public bool IsSuccessful;
public T Result;
// Constructors, members, etc.
}
public class ErrorReport : IConcludable { ... }
public class MathArg : IConcludable { ... }
public class ParseResult : IConcludable { ... }
Реализация
public Conclusion<ParseResult> ParseInput (string input)
{
// Parse input...
// Initialize ParseResult object...
return new Conclusion<ParseResult>(result);
}
Проблема
Когда я получаю окончательное значение, это встроенный тип типа int
, double
, string
, bool
и т.д. Я хотел бы использовать Conclusion<T>
как возврат, потому что у меня есть класс, который обрабатывает отчеты об ошибках, когда входная строка недействительна:
if (conclusion.ReturnObject is ErrorReport)
{
ErrorManager errorManager = new ErrorManager();
errorManager.Resolve(conclusion);
}
Исследование
Я искал ограничения.
Похоже, что ограничения только объединяются, поэтому включение интерфейсов каждого встроенного типа, который мне нужен, потребует определения горы методов, которые не имеют ничего общего с моей конструкцией Conclusion
.
Методы расширения
Это фактически изменяет поведение встроенных типов. Это не то, что я ищу, потому что мой интерфейс IConcludable
не имеет никаких методов.
Замена встроенных типов
Невозможно. Однако мне не нужно менять поведение этих типов. Я просто хочу добавить к нему пустой интерфейс.
Кажется, что нет никакого добавления интерфейса к встроенному типу. Я не уверен, что "Наследование" - это то, на что он будет ссылаться. Возможно ли это?
Edit
Лучшее объяснение выводов struct
Я использую вывод struct как возвращаемый объект в большинстве моих методов. Это потому, что я использую делегатов. См. Фактический код объектов ниже:
public delegate Conclusion<T> Validator<T>(T subclass) where T : IVerifiable<T>;
public delegate Conclusion<BaseFunction> Executor(BaseFunction subclass);
public struct Conclusion<T> where T : IConcludable
{
public bool IsSuccessful;
public T ReturnObject;
public Conclusion(T returnObject)
{
this.ReturnObject = returnObject;
this.IsSuccessful = returnObject is Error ? false : true;
}
}
public class BaseFunction : IVerifiable<BaseFunction>, IConcludable
{
public List<BaseArgument> Args;
public Executor Executing;
public Validator<BaseFunction> Validating;
public string UserInput;
public Conclusion<BaseFunction> Validate(BaseFunction subclass)
{
if (this.Validating != null)
{
return Validating(subclass);
}
else
{
StringBuilder message = new StringBuilder();
message.Append("A Validating delegate has not been assigned.");
throw new InvalidOperationException(message.ToString());
}
}
public Conclusion<BaseFunction> Execute(BaseFunction subclass)
{
if (this.Executing != null)
{
return this.Executing(subclass);
}
else
{
StringBuilder message = new StringBuilder();
message.Append("An Executing delegate has not been assigned.");
throw new InvalidOperationException(message.ToString());
}
}
}
public class Function<T> : BaseFunction
{
public T Result;
public Function()
{
base.Args = new List<BaseArgument>();
}
}
public class BaseArgument : IVerifiable<BaseArgument>, IConcludable
{
public string Role;
public string UserInput;
public int Position;
public Validator<BaseArgument> Validating;
public Conclusion<BaseArgument> Validate(BaseArgument subclass)
{
if (this.Validating != null)
{
return Validating(subclass);
}
else
throw new InvalidOperationException();
}
}
public class Argument<T> : BaseArgument
{
public T Value;
public Argument(int position)
{
base.Position = position;
}
}
public static class ExecutionHandler
{
public static Conclusion<BaseFunction> Sum(BaseFunction subclass)
{
subclass = (Function<double>)subclass;
// Execution code.
return new Conclusion<BaseFunction>(subclass);
}
public static Conclusion<BaseFunction> Concatenate(BaseFunction subclass)
{
subclass = (Function<double>)subclass;
// Execution code.
return new Conclusion<BaseFunction>(subclass);
}
}
Если мне нужно разместить больше, я сделаю это. но на самом деле это очень много. Тип возврата методов, назначенных всем делегатам, которые я использую, имеет тип возврата Conclusion<T>
, так что я могу иметь возвращаемый объект, а также ошибку, если это произойдет. Функции в приведенном выше коде возвращают Conclusion<BaseFunction>
, но этот возврат преобразуется в объект Addend<T>
, если он является числом. Если это часть другого типа функции, которая возвращает string
или bool
или другой тип, она преобразуется в другой тип класса. В конце числового вычисления возврат будет выглядеть как Conclusion<int>
или Conclusion<double>
. Поэтому добавление int
и double
в интерфейс IConcludable
- это то, что я пытаюсь сделать.
Лучшее объяснение приложения
Я пишу консольное приложение на С#. Он принимает данные от пользователя и записывает ответ. Ввод аналогичен формулам Excel: Sum(5, 15, Average(2, 3), 5)
или Concatenate("5 + 5 = ", Text(Sum(5, 5)))
. Строка ввода проверяется, анализируется и возвращает результат.