简体   繁体   中英

C# Generic Shorthand and Upcasting

I've been playing with interfaces and generics.

What I want is an Foo<T> to be a shorthand for Foo<T, int> Is this sensible? Is the following an accepted way of doing it?

using System.Diagnostics;

namespace MyNamespace
{
    public class Foo<T> : Foo<T, int> where T : class
    {
    }

    public class Foo<T, U> where T : class
    {
        public void Bar()
        {
            Debug.WriteLine("this: " + GetType().Name + ", T: " + typeof(T).Name + ", U: " + typeof(U).Name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var fooT = new Foo<string>();
            var fooTU = new Foo<string, int>();

            fooT.Bar();
            fooTU.Bar(); 
        }
    }
}

What my actual question is... is it possible to up (down?) cast from a Foo<T, int> to a Foo<T> where T is the same type. Does it even make sense to say this, or is this something to do with co/contravariance (which still eludes me)?

To me, a somewhat ignorant human, in this example Foo<string> and Foo<string, int> are identical types, but of course ((Foo<string>) fooTU).Bar(); does not work!

What my actual question is... is it possible to up (down?) cast from a Foo<T, int> to a Foo<T> where T is the same type. Does it even make sense to say this, or is this something to do with co/contravariance (which still eludes me)?

You can cast from Foo<string, int> to Foo<string> if the actual object is of type Foo<T> . The fact that they have the same name is completely irrelevant here, so let's change that:

class Foo<T, U> {}
class Bar<T> : Foo<T, int>

Now:

Foo<string, int> foo = new Foo<string, int>();
Bar<string> bar = (Bar<string>) foo; // Bang, throws

But:

Foo<string, int> foo = new Bar<string>();
Bar<string> bar = (Bar<string>) foo; // This is fine

The generics are pretty irrelevant here, really... it's the normal rules of casting.

is it possible to up cast from a Foo<T, int> to a Foo<T> where T is the same type.

Not safely - it's like casting from an Animal to a Dog - it might be a dog , but if it's not you're going to get an exception at run-time.

You also cannot take a Foo<string, int> and treat it like a Foo<string> for the same reason.

in this example Foo and Foo are identical types

This is incorrect. Foo<T> is a Foo<T,int> , but Foo<T,int> is not necessarily a Foo<T> . This is why you can cast from Foo<T> to Foo<T,int> , but not vice-versa.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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