I want to add an interface to some built-in types. I have an interface, IConcludable
, which I am using as a constraint for Conclusion<T>
. I have no clue how to approach this, or if it is even possible.
Basic Layout
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 { ... }
Implementation
public Conclusion<ParseResult> ParseInput (string input)
{
// Parse input...
// Initialize ParseResult object...
return new Conclusion<ParseResult>(result);
}
Problem
When I get the final value, it is a built-in type like int
, double
, string
, bool
, etc. I would like to use Conclusion<T>
as a return because I have a class that handles error reports when the input string is invalid:
if (conclusion.ReturnObject is ErrorReport)
{
ErrorManager errorManager = new ErrorManager();
errorManager.Resolve(conclusion);
}
Research
I looked into constraints.
It appears that constraints only add together, so including the interfaces of each built-in type that I need would require defining a mountain of methods that do not have anything to do with my Conclusion
struct.
Extension methods
These actually change the behavior of built-in types. It is not what I am looking for because my interface, IConcludable
, does not have any methods.
Replacing built-in types
Not possible. I don't need to change the behavior of these types though. I just want to add an empty interface to it.
There does not seem to be anything regarding adding an interface to a built-in type. I'm not sure if "Inheritance" is what it would be referred to. Is this possible?
Edit
Better explanation of Conclusion struct
I am using the conclusion struct as a return object in most of my methods. This is because I am using delegates. See the actual code of the objects below:
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);
}
}
If I need to post more, I will. but it's really a lot to look at. The return type of the methods assigned by all of the delegates I use have a return type of Conclusion<T>
so that I can have a return object as well as an error if one occurs. The functions in the code above return Conclusion<BaseFunction>
, but that return is converted into an object Addend<T>
if it is a number. If it is a part of another type of function that returns a string
or bool
or other type, it is converted into a different type of class. By the end of a numeric calculation, the return will be something like Conclusion<int>
or Conclusion<double>
. So adding int
and double
to the IConcludable
interface is what I am trying to do.
Better explanation of the application
I am writing a C# console application. It takes input from the user, and writes an answer. The input is similar to Excel formulas: Sum(5, 15, Average(2, 3), 5)
or Concatenate("5 + 5 = ", Text(Sum(5, 5)))
. The input string is validated, parsed, and returns a result.
An interface can extend other interfaces, just as a class subclass or extend another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces.
An interface can extend another interface in the same way that a class can extend another class. The extends keyword is used to extend an interface, and the child interface inherits the methods of the parent interface.
In TypeScript, interfaces can also extend classes, but only in a way that involves inheritance. When an interface extends a class, the interface includes all class members (public and private), but without the class' implementations.
Interfaces can inherit from one or more interfaces. The derived interface inherits the members from its base interfaces. A class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.
UPDATED (ADD MORE EXPLANATION)
As requested, I want to explain a bit more about my last answer.
Requirements
Conclusion
need to support both value type and reference type
IConcludable
)Solution:
AbstractConclusion
) that accepts Object
as generic inputstruct
and IConcluable
(have the ability to add more implementation, for ex: string)ORIGINAL ANSWER:
You can put the logic in AbstractConclusion
class, and have two implementations of it (Conclusion
which accepts IConcludeable
and PrimitiveConclusion
which accepts struct
data type)
See code sample below:
void Main()
{
PrimitiveConclusion<int> primitiveConclusion = new PrimitiveConclusion<int>(1);
Conclusion<ParseResult> parseResultConclusion = new Conclusion<ParseResult>(new ParseResult {});
Console.WriteLine($"{primitiveConclusion.Result.GetType()}");
Console.WriteLine($"{parseResultConclusion.Result.GetType()}");
}
public class TestClass
{
public Conclusion<ParseResult> ParseInput(string input)
{
return new Conclusion<ParseResult>(null);
}
}
public interface IConcludable { }
public abstract class AbstractConclusion<T>
{
public AbstractConclusion(T t)
{
IsSuccessful = t != null;
Result = t;
}
public bool IsSuccessful;
public T Result;
}
public class Conclusion<T> : AbstractConclusion<T> where T : IConcludable
{
public Conclusion(T t) : base(t)
{
}
}
public class PrimitiveConclusion<T> : AbstractConclusion<T> where T : struct
{
public PrimitiveConclusion(T t) : base(t)
{
}
}
public class ParseResult : IConcludable { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With