是否可以重载 C# 中的默认函数运算符(() 运算符)?如果是这样 - 怎么样?如果没有,是否有解决方法来产生类似的影响?
编辑:
我正在尝试为类提供默认运算符,类似于:
class A {
A(int myvalue) {/*save value*/}
public static int operator() (A a) {return a.val;}
....
}
...
A a = new A(5);
Console.Write(A());
编辑 2:
我已经阅读了规范,并且我知道没有直接的方法可以做到这一点。我希望有解决方法。
编辑 3: 动机是使一个类或一个实例表现得像一个函数,以创建一个方便的日志记录接口(interface)。顺便说一下,这在 C++ 中是可行且合理的。
最佳答案
Is it possible to overload the default function operator (the () operator) in C#? If so - how?
在 C# 中,只有方法和委托(delegate)才有意义作为函数调用。在 C# 中,委托(delegate)与 C++ 一样接近 function objects你问的是什么。
If not, is there a workaround to create a similar affect?
你无法准确地得到你想要的,但你可以模糊地接近(语法方面)。
使用重载的转换运算符
定义:
public static implicit operator DelegateType(TypeToConvert value)
{
return value.TheMethodToCall;
}
用法:
var someValue = new TypeToConvert();
DelegateType someValueFunc = someValue;
someValueFunc(value1);
这会获得您想要的最终语法,但需要您在指定类型的地方进行中间转换。
您可以通过以下方式做到这一点:
- 将您的值分配给局部变量,或将其传递给采用匹配委托(delegate)类型的函数(隐式转换)
- 转换它(显式转换)
使用索引器
定义:
public DelegateType this[ParameterType1 value1, ...]
{
get
{
// DelegateType would take no parameters, but might return a value
return () => TheMethodToCall(value1);
}
}
用法:
variable[value1]();
索引器版本的语法看起来很滑稽,但原始问题中的示例也是如此(标准 C# 习语)。它也有局限性,因为您不能定义采用零参数的索引器。
如果你想要一个无参数函数,一个解决方法是创建一个虚拟参数(可能是 object
类型)并向它传递一个一次性值(可能是 null
)。但是这个解决方案真的很糟糕,需要你深入了解它的用法。如果您想要一个采用您的虚拟类型的单个参数的重载,它也会中断。
The motivation is to make a class, or an instance behave like a function, to make a convenient logging interface
考虑到这种动机,我可能会建议您放弃上述选项。他们对这个问题太过分了。如果您扩大允许的解决方案,您可能会发现您更喜欢其中的一种。
改用动态
我提到的其他方法需要强类型,并且绝不是通用的。对于您所描述的内容,这可能是一个巨大的劣势。
如果你想要更弱的绑定(bind),你可以查看 Dynamic
.这将要求您调用命名方法,并且不允许您尝试实现的短语法。但它会松散地绑定(bind),并且可能会优雅地失败。
改用更简单的 .Net 功能
您还可以研究其他解决方案。
接口(interface):
使用标准化方法创建基本 ILoggable
接口(interface)。
扩展方法:
使用 .Log()
创建日志接口(interface) extension methods .扩展方法可以是通用的,并且可以采用基本类型,例如 object
,因此您不必修改现有的类来支持这一点。
覆盖 ToString
:
记录意味着您正在尝试将数据转换为文本(以便记录)。考虑到这一点,您可以简单地覆盖 ToString
方法。
您可以在所有这些情况下创建方法重载,但它们将与每种类型强绑定(bind)。不过,您在原始问题中请求的解决方案也与类型密切相关,因此这些解决方案并没有真正处于劣势。
现有解决方案
我见过的现有 .Net 日志记录库依赖于您覆盖 ToString
运算符。正如我上面所说,这是有道理的,因为您的日志是文本的。
有关 .Net 日志记录的先前技术,请参阅这些库:
- http://logging.apache.org/log4net/
- http://nlog-project.org/
- http://docs.castleproject.org/Windsor.Logging-Facility.ashx (通用记录器)
关于内置委托(delegate)类型的注意事项
确保使用 built-in delegate types在所有这些情况下,而不是定义您自己的委托(delegate)类型。最终会减少混淆,并要求您编写更少的代码。
// 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
关于c# - 在 C# 中重载函数调用运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2450153/