有没有一种方法可以扩展内置类型来继承接口

本文关键字:内置 扩展 置类型 接口 继承 方法 一种 有没有 | 更新日期: 2023-09-27 18:27:47

我想为一些内置类型添加一个接口。我有一个接口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);
}

问题

当我得到最终值时,它是一个内置类型,如intdoublestringbool等。我想使用Conclusion<T>作为返回,因为我有一个类在输入字符串无效时处理错误报告:

if (conclusion.ReturnObject is ErrorReport)
{
    ErrorManager errorManager = new ErrorManager();
    errorManager.Resolve(conclusion);
}

研究

我研究了约束

  • 对于"实数"类型,是否存在C#通用约束?[副本]

约束似乎只是加在一起的,所以包括我需要的每个内置类型的接口需要定义大量与我的Conclusion结构无关的方法。


扩展方法

  • 如何扩展C#内置类型,如String

这些实际上改变了内置类型的行为。这不是我想要的,因为我的接口IConcludable没有任何方法。

更换内置类型

  • 覆盖内置.NET类

不可能。不过,我不需要更改这些类型的行为。我只想给它添加一个空接口。

似乎没有任何关于向内置类型添加接口的内容。我不确定"继承"是否会被提及。这可能吗?

编辑

结论结构的更好解释

在我的大多数方法中,我都使用结论结构作为返回对象。这是因为我正在使用代理。请参阅以下对象的实际代码:

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>。如果它是返回stringbool或其他类型的另一类型函数的一部分,则它将转换为不同类型的类。在数值计算结束时,返回值将类似于Conclusion<int>Conclusion<double>。因此,将intdouble添加到IConcludable接口是我正在尝试做的

更好地解释应用程序

我正在编写一个C#控制台应用程序。它接受用户的输入,并编写一个答案。输入类似于Excel公式:Sum(5, 15, Average(2, 3), 5)Concatenate("5 + 5 = ", Text(Sum(5, 5)))。对输入字符串进行验证、解析并返回结果。

有没有一种方法可以扩展内置类型来继承接口

更新(添加更多解释)

根据要求,我想对我的最后一个回答做更多的解释。

要求

  • Conclusion需要同时支持值类型和引用类型
  • Generic
  • 值类型:所有数值数据类型(int、short、long等)、boolean、char、date
  • 引用类型:字符串和用户定义的类(在OP的示例中,IConcludable

解决方案:

  • 引入一个接受Object作为泛型输入的基类(AbstractConclusion
  • 将逻辑移动到基类以便重用
  • 介绍两个接受structIConcluable的新的具体实现(可以添加更多实现,例如:string)
  • 继承的类能够实现基类的所有方法

原始答案:

您可以将逻辑放在AbstractConclusion类中,并有两个实现(接受IConcludeableConclusion和接受struct数据类型的PrimitiveConclusion

参见下面的代码示例:

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 { }

使用where T : IConcludable泛型类型约束,不能将int作为泛型参数传递。而且也没有办法将接口附加到基元类型。

你可以做一些变通办法来做到这一点。您可以将Conclusion的主逻辑放入基本抽象类中并从中继承,将Conclusion重组为class(因为struct不支持继承)并创建类

public class Conclusion<T> : BaseConclusion
where T : IConcludable

public class PrimitiveConclusion<T> : BaseConclusion
where T : struct

此外,您还应该为string创建另一个类,因为string不是结构体,也没有实现IConcludable

正如我所知,没有其他方法可以将不同的类型作为泛型参数传递。


此外,您可以创建包装结构,而不是为内置类型创建Conclusion类,它将实现IConcludable。与达成协议

public struct Wrapper<T> : IConcludable
{
    public T Value { get; set; }
}