C# method generic return type casting

前端 未结 3 404
悲哀的现实
悲哀的现实 2020-12-10 15:32

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

相关标签:
3条回答
  • 2020-12-10 15:55

    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;

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-10 15:58

    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?

    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?

    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() { /* ... */ }
    }
    
    0 讨论(0)
  • 2020-12-10 16:10

    The second code snippet is impossible to compile because Rain is not 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. In other words - T foo() becomes 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. 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.

    0 讨论(0)
提交回复
热议问题