有没有办法扩展内置类型以继承接口?
Is there a way to extend a built-in type to inherit an interface?
我想为某些内置类型添加接口。我有一个接口 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>
作为 return 因为我有一个 class 在输入字符串无效时处理错误报告:
if (conclusion.ReturnObject is ErrorReport)
{
ErrorManager errorManager = new ErrorManager();
errorManager.Resolve(conclusion);
}
研究
我调查了约束。
- Is there a C# generic constraint for “real number” types? [duplicate]
似乎约束只是相加,因此包括我需要的每个内置类型的接口将需要定义一大堆与我的 Conclusion
结构无关的方法。
扩展方法
- How to extend C# built-in types, like String?
这些实际上改变了内置类型的行为。这不是我要找的,因为我的界面 IConcludable
没有任何方法。
替换内置类型
- Overwrite built in .NET class
不可能。不过,我不需要更改这些类型的行为。我只想给它添加一个空接口。
似乎没有关于向内置类型添加接口的任何内容。我不确定 "Inheritance" 是否是它所指的。这可能吗?
编辑
结论结构的更好解释
我在大多数方法中都将结论结构用作 return 对象。这是因为我正在使用委托。请参阅以下对象的实际代码:
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);
}
}
如果我需要 post 更多,我会的。但确实有很多值得一看的地方。我使用的所有委托分配的方法的 return 类型有一个 return 类型的 Conclusion<T>
这样我就可以有一个 return 对象以及一个错误如果一个发生。上面代码中的函数return Conclusion<BaseFunction>
,但是那个return如果是数字的话会转成一个对象Addend<T>
。如果它是 return 为 string
或 bool
或其他类型的另一种类型函数的一部分,则将其转换为不同类型的 class。在数值计算结束时,return 将类似于 Conclusion<int>
或 Conclusion<double>
。因此,将 int
和 double
添加到 IConcludable
界面就是我想要做的。
更好地解释应用程序
我正在编写 C# 控制台应用程序。它接受用户的输入,并写下答案。输入类似于 Excel 公式:Sum(5, 15, Average(2, 3), 5)
或 Concatenate("5 + 5 = ", Text(Sum(5, 5)))
。输入字符串经过验证、解析,并且 return 得到结果。
使用 where T : IConcludable
泛型类型约束,您不能将 int
作为泛型参数传递。而且也没有办法将接口附加到原始类型。
您可以采取一些解决方法来执行此操作。可以把Conclusion
的主要逻辑放到base abstract class中继承,将Conclusion
重构为class
(因为struct
不支持继承),创建 classes
public class Conclusion<T> : BaseConclusion
where T : IConcludable
和
public class PrimitiveConclusion<T> : BaseConclusion
where T : struct
并且您还应该为 string
创建另一个 class,因为 string
不是结构并且没有实现 IConcludable
据我所知,没有其他方法可以将不同类型作为泛型参数传递。
此外,您可以创建包装器结构,而不是为内置类型创建 Conclusion
class,它将实现 IConcludable
。并与之达成协议
public struct Wrapper<T> : IConcludable
{
public T Value { get; set; }
}
已更新(添加更多说明)
根据要求,我想对我的上一个回答做更多的解释。
要求
Conclusion
需要同时支持值类型和引用类型
- 通用
- 值类型:所有数字数据类型(int、short、long 等)、boolean、char、date....
- 引用类型:字符串和用户定义的class(在OP的示例中,
IConcludable
)
解法:
- 引入接受
Object
作为通用输入的基 class (AbstractConclusion
)
- 将逻辑移至基础 class 以供重用
- 引入两个接受
struct
和IConcluable
的新具体实现(能够添加更多实现,例如:字符串)
- 被继承的classes可以使用baseclass
的所有方法
原始答案:
您可以将逻辑放在 AbstractConclusion
class 中,并有两个实现(Conclusion
接受 IConcludeable
和 PrimitiveConclusion
接受 struct
数据类型)
参见下面的代码示例:
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 { }
我想为某些内置类型添加接口。我有一个接口 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>
作为 return 因为我有一个 class 在输入字符串无效时处理错误报告:
if (conclusion.ReturnObject is ErrorReport)
{
ErrorManager errorManager = new ErrorManager();
errorManager.Resolve(conclusion);
}
研究
我调查了约束。
- Is there a C# generic constraint for “real number” types? [duplicate]
似乎约束只是相加,因此包括我需要的每个内置类型的接口将需要定义一大堆与我的 Conclusion
结构无关的方法。
扩展方法
- How to extend C# built-in types, like String?
这些实际上改变了内置类型的行为。这不是我要找的,因为我的界面 IConcludable
没有任何方法。
替换内置类型
- Overwrite built in .NET class
不可能。不过,我不需要更改这些类型的行为。我只想给它添加一个空接口。
似乎没有关于向内置类型添加接口的任何内容。我不确定 "Inheritance" 是否是它所指的。这可能吗?
编辑
结论结构的更好解释
我在大多数方法中都将结论结构用作 return 对象。这是因为我正在使用委托。请参阅以下对象的实际代码:
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);
}
}
如果我需要 post 更多,我会的。但确实有很多值得一看的地方。我使用的所有委托分配的方法的 return 类型有一个 return 类型的 Conclusion<T>
这样我就可以有一个 return 对象以及一个错误如果一个发生。上面代码中的函数return Conclusion<BaseFunction>
,但是那个return如果是数字的话会转成一个对象Addend<T>
。如果它是 return 为 string
或 bool
或其他类型的另一种类型函数的一部分,则将其转换为不同类型的 class。在数值计算结束时,return 将类似于 Conclusion<int>
或 Conclusion<double>
。因此,将 int
和 double
添加到 IConcludable
界面就是我想要做的。
更好地解释应用程序
我正在编写 C# 控制台应用程序。它接受用户的输入,并写下答案。输入类似于 Excel 公式:Sum(5, 15, Average(2, 3), 5)
或 Concatenate("5 + 5 = ", Text(Sum(5, 5)))
。输入字符串经过验证、解析,并且 return 得到结果。
使用 where T : IConcludable
泛型类型约束,您不能将 int
作为泛型参数传递。而且也没有办法将接口附加到原始类型。
您可以采取一些解决方法来执行此操作。可以把Conclusion
的主要逻辑放到base abstract class中继承,将Conclusion
重构为class
(因为struct
不支持继承),创建 classes
public class Conclusion<T> : BaseConclusion
where T : IConcludable
和
public class PrimitiveConclusion<T> : BaseConclusion
where T : struct
并且您还应该为 string
创建另一个 class,因为 string
不是结构并且没有实现 IConcludable
据我所知,没有其他方法可以将不同类型作为泛型参数传递。
此外,您可以创建包装器结构,而不是为内置类型创建 Conclusion
class,它将实现 IConcludable
。并与之达成协议
public struct Wrapper<T> : IConcludable
{
public T Value { get; set; }
}
已更新(添加更多说明)
根据要求,我想对我的上一个回答做更多的解释。
要求
Conclusion
需要同时支持值类型和引用类型- 通用
- 值类型:所有数字数据类型(int、short、long 等)、boolean、char、date....
- 引用类型:字符串和用户定义的class(在OP的示例中,
IConcludable
)
解法:
- 引入接受
Object
作为通用输入的基 class (AbstractConclusion
) - 将逻辑移至基础 class 以供重用
- 引入两个接受
struct
和IConcluable
的新具体实现(能够添加更多实现,例如:字符串) - 被继承的classes可以使用baseclass 的所有方法
原始答案:
您可以将逻辑放在 AbstractConclusion
class 中,并有两个实现(Conclusion
接受 IConcludeable
和 PrimitiveConclusion
接受 struct
数据类型)
参见下面的代码示例:
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 { }