这可能是一个相当复杂的问题,但只是检查是否有答案。
考虑有两种扩展方法大致看起来像这样(并且在另一个我无法控制的程序集中):
public static class ExtensionMethods
{
public static string ConversionA<T>(this T self) { /* .... */ }
public static string ConversionB<T>(this T self) { /* .... */ }
} // eo class ExtensionMethods
我有一个在对象上使用此扩展方法的方法。理想情况下,我希望调用者明确指定使用哪个转换函数,但必要时默认使用,所以我希望我可以将签名转换为Func<>
:
public static class Config
{
public static T Read<T>(string fileName, Func<T, string> = ExtensionMethods.ConversionA<T>)
{
}
} // eo class Config
这有可能吗?我知道这是一个很长的镜头:)
答案 0 :(得分:4)
这有可能吗?
当然 - 你无法做的唯一事情就是让Func
成为可选参数。可选参数的默认值必须是编译时常量。
可以通过重载来实现:
public static T Read<T>(string fileName, Func<T, string> func) // non-optional parameter
{
/* ... */
}
public static T Read<T>(string fileName)
{
return Read<T>(fileName, ExtensionMethods.ConversionA<T>);
}
答案 1 :(得分:1)
修改强>
不幸的是我错过了你要求定义默认方法的地方。这不可能。 C#明确禁止为非编译时常量的任何内容分配默认参数。解决这个问题的唯一方法是设置一些重载方法,如下:
public static T Read<T>(T input)
{
Read(input, ExtensionMethods.ConversionA<T>);
}
public static T Read<T>(T input, Func<T, string> conversion)
{
// Logic goes here
}
总而言之,它并不是那么糟糕。这是一些额外的代码,它将为您提供您正在寻找的行为。
<强>原始强>
看起来你所拥有的应该基本上起作用。您只需指定它接受Func<T, string>
即可。您无法强制始终为ConversionA<T>
或ConversionB<T>
,但这些类型签名中的任何一个都应满足Func<T, string>
。
例如(不知道你的转换方法做了什么,我将自己编造):
public static class Conversions
{
public static string UpperString<T>(T self)
{
return self.ToString().ToUpper();
}
public static string LowerString<T>(T self)
{
return self.ToString().ToLower();
}
}
public static T Read<T>(T input, Func<T, string> conversion)
{
// Do-whatchya-do
}
void Main()
{
Read<SomeObj>(new SomeObj(), Conversions.UpperString<SomeObj>);
Read<SomeObj>(new SomeObj(), Conversions.LowerString<SomeObj>);
}
当你最终调用“Read”时,你只需要传递具有正确类型的泛型方法。因此,您可能需要稍微复制类型签名,但它应该可以正常工作。
他们是扩展方法没有任何改变。任何扩展方法都可以显式地以非扩展格式使用。例如:
public static class Extensions
{
public static T SomeExtension<T>(this T value) { /* ... */ }
}
可以通过以下方式在两者中调用:
someT.SomeExtension();
Extensions.SomeExtension(someT);