可以将c#扩展方法添加到f#类型中吗?

本文关键字:类型 添加 扩展 方法 | 更新日期: 2023-09-27 18:16:11

我有别人的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"

知道为什么吗?

可以将c#扩展方法添加到f#类型中吗?

正如其他人指出的那样,ToString对象总是比扩展方法更好的匹配。您可能应该更改扩展方法的签名;更改名称可能是正确的方法。

而且:你说这个东西的目的是为了方便调试。重写ToString可能是错误的;ToString可以用于除调试之外的其他用途。我将倾向于创建我自己的特殊命名的方法,其名称清楚地反映了方法的目的。

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

如果您想以有趣的方式显示复杂的数据结构,可以考虑编写一个Debugger Visualizer。

你的问题的答案是"是"。但是,您的示例没有成功,因为方法解析在找到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());

我认为你不能这样做,因为ToString()总是在那里,在CLR世界的任何对象。看看Eric Lippert的回答

您可以创建一个覆盖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;