一个C#扩展方法可以被添加到F#类型中吗?

3

我有一个包含类型的F#库:

module HisModule

type hisType {
    a : float;
    b : float;
    c : float;
}

我正在使用C#,想要为它添加一个"ToString()"方法,以便于调试。

但是以下代码似乎无法实现:

public static class MyExtensions
{
    public static string ToString(this HisModule.hisType h)
    {
        return String.Format("a={0},b={1},c={2}", h.a, h.b, h.c);
    }
}
....
var h = new hisType();
Console.WriteLine(h.ToString());  // prints "HisModule+hisType"

有什么想法为什么不行?

1
请注意,在.NET中的每个对象已经具有ToString()成员方法。 - DuckMaestro
可能是如何为toString创建扩展方法?的重复问题。 - ildjarn
4个回答

11

正如其他人所指出的,object类型的ToString方法总是比你的扩展方法更好。你应该改变你的扩展方法的签名,改变名称可能是正确的方式。

此外: 你说这个东西的目的是为了方便调试。重写ToString可能不是正确的做法; ToString可能被用于除调试之外的其它用途。我倾向于创建一个自己特别命名的方法,它的名称清楚地反映了方法的目的。

如果你正在创建一个新类型,并希望在调试器中有特殊的显示行为,则最简单的方法是使用调试器显示属性

如果你想要以有趣的方式显示一个复杂的数据结构,考虑编写一个调试器可视化程序


6
你的问题的答案是“Yes”。 然而,你的示例并没有成功,因为当方法解析找到object.ToString()时,它就会成功,所以编译器不会查找扩展方法。请尝试使用其他名称:
public static class MyExtensions 
{ 
    public static string Foo(this HisModule.hisType h) 
    { 
        return String.Format("a={0},b={1},c={2}", h.a, h.b, h.c); 
    } 
} 

....   
var h = new hisType();   
Console.WriteLine(h.Foo());

3

我认为你无法做到这一点,因为ToString()在CLR世界中的任何对象中都存在。请参阅Eric Lippert回答


我过去一直在枚举类型上添加ToString()扩展方法,因此我不认为这肯定是问题,解决办法应该回退到Object.ToString()最后。 - David Grenier
2
@DavidGrenier:重载决议始终优先于基类型上的适用候选方法而不是扩展方法。您能演示C#不这样做的情况吗?如果是这样,那么您已经发现了一个错误,我想知道它。谢谢! - Eric Lippert
我尝试在 LINQPad 中重复实验,但它没有成功。可能只是我自己疯了。这是在之前的工作场所完成的,证据显然不支持我的想法。 - David Grenier

0
你可以创建一个包装类型(带有隐式转换),它重写了ToString方法。
class MyType {
    private readonly hisType _hisType;
    private MyType(hisType hisType) {
        _hisType = hisType;
    }
    public static implicit operator MyType(hisType hisType) {
        return new MyType(hisType);
    }
    public override string ToString() {
        return String.Format("a={0},b={1},c={2}", _hisType.a, _hisType.b, _hisType.c);
    }
}

hisType y;
MyType x = y;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接