Asa*_*f R 28 c# operator-overloading
是否可以在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());
Run Code Online (Sandbox Code Playgroud)
编辑2:
我已阅读规范,我知道没有直接的方法来做到这一点.我希望有一个解决方法.
编辑3:动机是使一个类或一个实例表现得像一个函数,以创建一个方便的日志记录界面.顺便说一句,这在C++中是可行和合理的.
Chr*_*ens 17
那没有.C#规范的第7.2.2节将可重载运算符定义为:
UNARY:+ - !〜++ - true false
BINARY:+ - */%&| ^ << >> ==!=> <> = <=
无论如何,你的可读性都会变得一团糟.也许有另一种方法来实现你想要做的事情?
Mer*_*ham 14
是否可以在C#中重载默认函数运算符((运算符)?如果是这样 - 怎么样?
在C#中,只有方法和委托才能作为函数调用.在C#中,委托与您询问的C++ 函数对象一样接近.
如果没有,是否有解决方法来创建类似的影响?
你无法得到你想要的东西,但你可以模糊地接近(语法方面).
使用重载转换运算符
定义:
public static implicit operator DelegateType(TypeToConvert value)
{
return value.TheMethodToCall;
}
Run Code Online (Sandbox Code Playgroud)
用法:
var someValue = new TypeToConvert();
DelegateType someValueFunc = someValue;
someValueFunc(value1);
Run Code Online (Sandbox Code Playgroud)
这将获得您想要的最终语法,但需要您在指定类型的情况下进行中间转换.
你可以这样做:
使用索引器
定义:
public DelegateType this[ParameterType1 value1, ...]
{
get
{
// DelegateType would take no parameters, but might return a value
return () => TheMethodToCall(value1);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
variable[value1]();
Run Code Online (Sandbox Code Playgroud)
索引器版本具有看似滑稽的语法,但原始问题中的示例也是如此(标准C#惯用法).它也是有限的,因为您无法定义一个零参数的索引器.
如果你想要一个无参数函数,解决方法是创建一个虚拟参数(可能是类型object)并将一个丢弃值传递给它(可能null).但是这个解决方案真的很糟糕,需要你深入了解其用法.如果你想要一个带有虚拟类型的单个参数的重载,它也会破坏.
动机是使一个类或一个实例表现得像一个函数,以创建一个方便的日志记录界面
考虑到这种动机,我可能会建议你放弃上面的选择.他们对这个问题有点过分.如果您扩大您允许的解决方案,您可能会发现您更喜欢其中一个.
使用动态代替
我提到的其他方法需要强类型,并且绝不是通用的.对于您所描述的内容,这可能是一个巨大的劣势.
如果你想要更弱的绑定,你可以考虑一下Dynamic.这将要求您调用命名方法,并且不允许您尝试实现的短语法.但它会松散地束缚,并且可能会优雅地失败.
使用更简单的.Net功能
您可以查看其他解决方案.
接口:
ILoggable使用标准化方法创建基本接口.
扩展方法:
使用.Log() 扩展方法创建日志记录界面.扩展方法可以是通用的,并且可以采用基类型object,因此您不必修改现有的类来支持它.
覆盖ToString:
记录意味着您正在尝试将数据转换为文本(因此可以记录).考虑到这一点,您可以简单地覆盖该ToString方法.
您可以在所有这些情况下创建方法重载,但它们将强烈绑定到每种类型.您在原始问题中请求的解决方案也与该类型密切相关,因此这些解决方案并非真正处于劣势.
现有解决方案
我见过的现有.Net日志库依赖于你覆盖ToString运营商.正如我上面所说,这是有道理的,因为你的日志是文本的.
有关.Net日志的先前技术,请参阅以下库:
关于内置委托类型的注意事项
确保在所有这些情况下使用内置委托类型,而不是定义自己的委托类型.它最终会减少混乱,并要求您编写更少的代码.
// 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
Run Code Online (Sandbox Code Playgroud)
不,(这是不正确的,请参阅下面的Eric Lippert的评论)括号是C#语法的一部分,用于表示传递给方法的一组参数. ()不是运营商,因此不能超载.()只是表明有问题的方法没有指定正式参数,因此不需要参数.
你想做什么?也许如果你给出了一个问题的小例子,我们就可以帮助解决问题.
编辑:好的,我看到你现在得到了什么.你总是可以像这样创建一个映射到实例上的方法的委托(给定class A定义这样的方法:) public void Foo() { }:
Action action = someA.Foo;
Run Code Online (Sandbox Code Playgroud)
然后你可以用这样一个简单的语法调用委托:
action();
Run Code Online (Sandbox Code Playgroud)
不幸的是(或者不是,取决于你的偏好),这几乎与C#一样可以让你获得这种语法.
是的,这绝对可以通过dynamic类型来完成(更多信息可在此处找到)。
using System.Dynamic.DynamicObject
class A : DynamicObject
{
private int val;
A(int myvalue)
{
this.val = myvalue;
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) {
result = this.val;
return true;
}
}
...
dynamic a = new A(5);
Console.Write(a());
Run Code Online (Sandbox Code Playgroud)
该dynamic类型的装置,该类型完全假定在运行时允许更大的flexability几乎所有与对象相互作用。
我假设你想用的a,而不是A在Console.Write行。
| 归档时间: |
|
| 查看次数: |
15149 次 |
| 最近记录: |