是否可以重载 C# 中的默认函数运算符(() 运算符)?如果是 - 如何?
在 C# 中,只有方法和委托才能作为函数调用。在 C# 中,委托与您所询问的 C++ function objects 一样接近。
如果没有,是否有解决方法来产生类似的影响?
你不能得到你想要的,但你可以模糊地接近(语法方面)。
使用重载的转换运算符
定义:
public static implicit operator DelegateType(TypeToConvert value)
{
return value.TheMethodToCall;
}
用法:
var someValue = new TypeToConvert();
DelegateType someValueFunc = someValue;
someValueFunc(value1);
这将获得您想要的最终语法,但需要您在指定类型的地方进行中间转换。
您可以这样做:
- 将值分配给局部变量,或将其传递给采用匹配委托类型的函数(隐式转换)
- 强制转换(显式转换)
使用索引器
定义:
public DelegateType this[ParameterType1 value1, ...]
{
get
{
// DelegateType would take no parameters, but might return a value
return () => TheMethodToCall(value1);
}
}
用法:
variable[value1]();
索引器版本的语法看起来很有趣,但原始问题中的示例也是如此(使用标准 C# 习惯用法)。它也受到限制,因为您无法定义采用零参数的索引器。
如果您想要一个无参数函数,一种解决方法是创建一个虚拟参数(可能是object 类型)并将一个丢弃值传递给它(可能是null)。但这个解决方案真的很恶心,需要你深入了解它的用法。如果您想要一个采用虚拟类型的单个参数的重载,它也会中断。
动机是让一个类或一个实例表现得像一个函数,以制作一个方便的日志接口
考虑到这个动机,我可能会建议你放弃上面的那些选项。他们在这个问题上太过分了。如果您扩大允许的解决方案,您可能会发现您更喜欢其中之一。
改用动态
我提到的其他方法需要强类型,绝不是通用的。对于您所描述的内容,这可能是一个巨大的劣势。
如果你想要更弱的绑定,你可以查看Dynamic。这将要求您调用命名方法,并且不允许您尝试实现的短语法。但它会松散地绑定,并且可以优雅地失败。
改用更简单的 .Net 功能
您还可以研究其他解决方案。
接口:
使用标准化方法创建一个基本的ILoggable 接口。
扩展方法:
使用.Log() extension methods 创建您的日志接口。扩展方法可以是通用的,并且可以采用基本类型,例如object,因此您不必修改现有的类来支持它。
覆盖ToString:
记录意味着您正在尝试将数据转换为文本(以便记录)。考虑到这一点,您可以简单地覆盖 ToString 方法。
在所有这些情况下,您都可以创建方法重载,但它们将被强绑定到每种类型。但是,您在原始问题中请求的解决方案也与类型密切相关,因此这些解决方案并不是真正处于劣势。
现有解决方案
我见过的现有 .Net 日志库依赖于您覆盖 ToString 运算符。正如我上面所说,这是有道理的,因为您的日志是文本的。
有关 .Net 日志记录的先前技术,请参阅以下库:
关于内置委托类型的注意事项
确保在所有这些情况下都使用built-in delegate types,而不是定义自己的委托类型。最终会减少混乱,并且需要您编写更少的代码。
// function that returns void
Action a1 = ...;
Action<TParameter1> a2 = ...;
Action<TParameter1, TParameter2> a3 = ...;
// etc
// function that returns a value
Func<TReturn> f1 = ...;
Func<TParameter1, TReturn> f2 = ...;
Func<TParameter1, TParameter2, TReturn> f3 = ...;
// etc