C#方法通用返回类型转换

时间:2018-11-12 09:15:54

标签: c# generics

我正在尝试在具有通用返回类型的接口中创建方法,但是我无法将通用类型转换为特定的类型/类。但是,如果我将泛型而不是方法放在接口上,我就能进行转换。

换句话说,为什么这样做

public class Rain {
    public string propA {get;set;}
}
public interface IFoo<T> {
    T foo();
}

public class Bar : IFoo<Rain> {
    Rain foo() { 
        //...
        return new Rain();
    }
}

public bar = new Bar();
Rain rain = bar.foo();

但这不可能吗?

public class Rain {
    public string propA {get;set;}
}
public interface IFoo {
    T foo<T>();
}

public class Bar : IFoo {
    T foo<T>() { 
        //...
        return new Rain();
    }
}

public bar = new Bar();
Rain rain = bar.foo<Rain>();

还有其他解决方法(不使用Convert.ChangeType())吗?

3 个答案:

答案 0 :(得分:11)

第二个代码段无法编译,因为Rain不是T

当在类中提供type参数时,没有问题,因为该方法只能返回在类声明中已经提供的类型。换句话说,T foo()变成Rain foo

但是,当将类型参数提供给方法时,该方法必须返回提供给它的任何类型-因此,您只能返回T以外的任何值。换句话说,编译器不能强制调用方法仅使用foo<Rain>(),而是可以强制foo方法返回T

答案 1 :(得分:3)

区别是:

// On this line you specify that the interface's generic type paramter 'T' is of type 'Rain',
// so the method implements the interface and returns a 'Rain'
public class Bar : IFoo<Rain> {
    Rain foo() { // <= implements IFoo<Rain>.foo, where T = Rain so foo returns 'Rain'
        return new Rain();

// In this version, the generic type parameter is declared on the method. It could be any type when the method is called, yet you always return a 'Rain'
public class Bar : IFoo {
    T foo<T>() { // <= implements IFoo.foo<T> but the type of T is not specified yet
        return new Rain();

“解决方案”取决于您的意图。

  • 您为什么要在界面上使用通用参数?
  • 而且,如果始终总是返回foo,为什么还要在Rain方法上使用通用参数?

当然,无论如何,您都可以像这样进行投射:

T Foo<T>()
{
    object result;
    result = new Rain();
    return (T)result; // note, this will throw at runtime if 'result' cannot be cast to 'T'
}

// call like this:
Bar.Foo<Rain>();

但是我认为您的第一种方法IFoo<T>很有意义,那么为什么不使用它呢?

更新

根据您的评论:您还可以定义多个通用参数:

public interface IFoo<T1, T2>
{
    T1 foo();
    T2 foo2();
}

// implementation:
public class Bar : IFoo<Rain, Other>
{
    Rain foo() { /* ... */ }
    Other foo2() { /* ... */ }
}

答案 2 :(得分:0)

如果您需要您的接口支持一组任意的类,并且使用的类由调用者确定,那么类似这样的方法是最通用的解决方案。

public class Bar : IFoo {
    T foo<T>() { 
        if (typeof(T)==typeof(Rain))
           return new Rain() as T;
        if (typeof(T)==typeof(Snow))
           return new Snow() as T;
        Throw new ArgumentException("Not implemented for " + typeof(T).Name);
    }
}

如果您所有的T都有一个通用的接口,而这正是您感兴趣的,那么您可以这样做;

public class Snow : IWeather {...}
public class Rain: IWeather {...}
public class Bar : IFoo {
    IWeather  foo<T>() T : IWeather { 
        if (typeof(T)==typeof(Rain))
           return new Rain();
        if (typeof(T)==typeof(Snow))
           return new Snow();
        Throw new ArgumentException("Not implemented for " + typeof(T).Name);
    }
}