从接口重载泛型方法

时间:2016-07-26 08:33:32

标签: c#

我有一个通用方法的接口:

interface IConverter
{
    void Convert<T>(T value);
}

我想为任何类型实现它,但我也知道,对于string,方法逻辑可以简化,所以我想专门为string重载它(就像在{ {3}}):

class Converter : IConverter
{
    public void Convert<T>(T value)
    {
        Console.WriteLine("Generic Method " + value);
    }

    public void Convert(string value)
    {
        Console.WriteLine("String Method " + value);
    }
}

当我有Converter的实例并直接调用方法时,它工作正常。代码

var converter = new Converter();
converter.Convert("ABC");
converter.Convert(123);

输出

String Method ABC
Generic Method 123

然而,当我使用界面时(就像在带有DI的任何应用程序中),我无法调用string的重载。代码

var converter = (IConverter)new Converter();
converter.Convert("ABC");
converter.Convert(123);

输出:

Generic Method ABC
Generic Method 123

无论如何要完成调用string重载方法而不进行类型检查,如

if (typeof(T) == typeof(string))
    ...

5 个答案:

答案 0 :(得分:3)

没有。您将converter投射到IConverter,因此converter变量只显示一种方法:Convert<T>(T value)

您可以通过在界面中添加Convert(string)来解决此问题,或者根本不投放到界面并继续使用您的Converter课程。只有这样才能看到其他方法。

答案 1 :(得分:1)

有两种方法,

您可以在界面中包含该方法,例如

interface IConverter
{
    void Convert<T>(T value);
    void Convert(string value);
}

将特定于string的方法设为扩展方法

public static void Convert(this string str, string value)
{
  // code here
}

答案 2 :(得分:1)

也许你的设计是倒置的,你的界面应该是通用的:

interface IConverter<T>
{
    void Convert(T value);
}

这将允许您以特定方式实现特定类型:

class BaseConverter<T> : IConverter<T>
{
    public void Convert(T value) 
    { /* some common way */ }
}

class StringConverter : IConverter<string>
{
    public void Convert(string value) 
    { /* strings get converted here */ }
}

你可能会有一个&#34;工厂&#34;将提供正确的转换器实例的类:

class ConverterFactory
{
    // this is basically "poor man's" service locator,
    // but the same idea works with DI, where you
    // would register individual comparers 

    public IConverter<T> Create<T>()
    {
         // use a Dictionary, or add that
         // typeof(T) == typeof(string) check here
    }
}

这类似于例如在.NET BCL中定义IComparer<T>并与Comparer<T>.Default结合的方式。

这也是可以更好地使用DI的方法,因为您的IConverter<T>取决于T,而拥有单个非泛型IConverter无法告诉DI注入哪个特定实例

答案 3 :(得分:0)

可以在你的泛型方法中进行一些类型检查。

public void Convert<T>(T value)
{
    Console.WriteLine(typeof(T) == typeof(string) ? "String Method" : "Generic Method " + value);
}

但这样做会省略所有泛型的内容,不是吗?说不推荐这个。

无论如何只是因为两个方法具有相同的名称并不意味着它们 相等,因为编译器Convert(string)Convert<T>(T)完全相同不同的方法。然而,接口只知道通用接口,因此当转换为接口时,根本不知道字符串方法。

正如Patrick已经提到的那样,在界面上省略了强制转换或实现了string-method。另一个 - 也是肮脏的黑客 - 将通用调用重定向到字符串方法:

class Converter : IConverter
{
    public void Convert<T>(T value)
    {
        if (typeof(T) == typeof(string) this.Convert((string) value);
        else Console.WriteLine("Generic Method " + value);
    }

    public void Convert(string value)
    {
        Console.WriteLine("String Method " + value);
    }
}

答案 4 :(得分:0)

如果你真的想要保持界面相同,你可以使用类型检查:

class Converter : IConverter
{
    public void Convert<T>(T value)
    {
        if (value is string)
        {
            Console.WriteLine("String Method " + (string)value);
        }
        else
        {
            Console.WriteLine("Generic Method " + value);
        }
    }
}

或者,正如其他人所说,您可以将Convert(string)添加到IConverter。