简体   繁体   English

C#方法泛型返回类型转换

[英]C# method generic return type casting

I am trying to create a method in an interface with a generic return type but I fail to cast the generic to a specific type/class. 我试图在具有泛型返回类型的接口中创建一个方法,但我无法将泛型强制转换为特定的类型/类。 But if I put the generic on the interface instead of the method I am able to do the casting. 但是,如果我将泛型放在接口上而不是方法上,我可以进行转换。

In other words, why does this work 换句话说,为什么这样做

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();

But it is not possible to do this? 但是不可能这样做吗?

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>();

Is there any other way around ( without using Convert.ChangeType() )? 有没有其他方法(不使用Convert.ChangeType() )?

The second code snippet is impossible to compile because Rain is not T . 第二个代码片段无法编译,因为Rain不是T

When the type parameter is supplied in the class, there's no problem because the method can only return the type that was already supplied in the class declaration. 在类中提供type参数时,没有问题,因为该方法只能返回类声明中已提供的类型。 In other words - T foo() becomes Rain foo . 换句话说 - T foo()成为Rain foo

However, when the type parameter is supplied to the method, then the method is obligated to return whatever type is supplied to it - so you can't return anything other than T . 但是,当类型参数提供给方法时,该方法必须返回提供给它的任何类型 - 因此您不能返回除T之外的任何类型。 In other words, the compiler can't enforce the calling method to only use foo<Rain>() , but it can enforce the foo method to return T . 换句话说,编译器不能强制调用方法只使用foo<Rain>() ,但它可以强制foo方法返回T

The difference is: 不同之处是:

// 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();

The "solution" for this depends on what your intentions are. 这个“解决方案”取决于你的意图。

  • Why would you not want the generic parameter on the interface? 你为什么不想接口的泛型参数?
  • Also, why would you want a generic parameter on the foo method, if you always return Rain anyways? 另外,如果你总是返回Rain ,你为什么要在foo方法上使用泛型参数呢?

Of course, in any case, you could just cast it like this: 当然,无论如何,你可以像这样投出它:

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>();

But I think your first approach IFoo<T> makes perfect sense so why not use it? 但我认为你的第一种方法IFoo<T>非常有意义,为什么不使用呢?

UPDATE UPDATE

Based on your comment: You can also define multiple generic parameters: 根据您的评论:您还可以定义多个通用参数:

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

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

If you need your interface to support an arbitrary set of classes, and what classes are used is determined by the caller then something like this is the most general solution. 如果你需要你的接口支持任意一组类,并且调用者确定使用哪些类,那么像这样的东西是最通用的解决方案。

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);
    }
}

If all your T's have a common interface and that is what you are interested in you could do; 如果你所有的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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM