Generics and static members

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Filip Zawada

    Generics and static members

    Hi,

    I've encountered a rather interesting language problem. Suppose I've
    got following types:

    //class providing usefull static methods
    public class GoodBase<T>
    {
    public static void Met(){};
    }

    public class SomeEntity
    : GoodBase<SomeEn tity>
    {
    }

    public interface IDictModel<T>
    where T : GoodBase<T>
    {
    }

    public class DictModel<T>
    : IDictModel<T>
    where T : GoodBase<T>
    {
    public void Test()
    {
    GoodBase<SomeEn tity>.Met(); //OK
    SomeEntity.Met( ); //OK
    T.Met(); //won't compile
    }
    }

    The question is why can't I call a static method using generic
    parameter?

    I've specified that T is of type GoodBase<T>, so static methods from
    GoodBase should be available by using generic parameter... Isn't
    GoodBase<SomeEn tity>.Met() actually the same as T.Met()? Why do I have
    to repeat myself?

    Regards,
    Filip Zawada
  • Peter Duniho

    #2
    Re: Generics and static members

    On Fri, 19 Sep 2008 09:27:25 -0700, Filip Zawada <fzawada@gmail. comwrote:
    [...]
    The question is why can't I call a static method using generic
    parameter?
    >
    I've specified that T is of type GoodBase<T>, so static methods from
    GoodBase should be available by using generic parameter... Isn't
    GoodBase<SomeEn tity>.Met() actually the same as T.Met()? Why do I have
    to repeat myself?
    You don't. But, you also can't use T directly as the type.

    It doesn't make sense to call static members on the type parameter. This
    is true regardless of whether or not the type parameter inherits a generic
    type or a non-generic one. Consider:

    class A
    {
    public static void MethodA() { }
    }

    class B<T: where T : A
    {
    public void MethodB()
    {
    T.MethodA();
    }
    }

    One of two possible behaviors may be expected here.

    First, it may be expected that if the class T reimplements MethodA(), you
    want the implementation in the most-derived class to be called. That is,
    if T is not A and has its own implementation of MethodA, you want _that_
    implementation to be called rather than A.MethodA.

    If this is the case, then it's not possible for the compiler to fulfill
    your intent, because it needs to know when it compiles the _generic_ class
    how to get at the method, and at that point the type parameter hasn't
    actually been resolved yet.

    I suppose in theory, the compiler could generate some complex code to use
    reflection to determine at run-time the correct static method to call.
    But that could lead to a serious, non-obvious performance problem at best,
    and at worst could cause some subtle, hard-to-find bugs. It's wise for
    the language design to prohibit the use of a type parameter in that
    context.

    Of course, there's nothing stopping you from writing such code
    explicitly. But in that case, it would be obvious looking at the code
    that's what you're doing.

    Alternatively, maybe you always want to call A.MethodA. If that's the
    intent of the code, then you can get it to work by doing exactly that:

    class B<T: where T : A
    {
    public void MethodB()
    {
    A.MethodA();
    }
    }

    Note that if T inherits a generic type, then you can use the same
    technique, supplying the type parameter:

    class A<T>
    {
    public static void MethodA() { }
    }

    class B<T: where T : A<T>
    {
    public void MethodB()
    {
    A<T>.MethodA() ;
    }
    }

    In your own example, it would look like this:

    public class DictModel<T>
    : IDictModel<T>
    where T : GoodBase<T>
    {
    public void Test()
    {
    GoodBase<SomeEn tity>.Met(); //OK
    SomeEntity.Met( ); //OK
    GoodBase<T>.Met (); //OK
    }
    }

    That ensures that if the Met() method depends on the type parameter, that
    you actually get the implementation you desire (as opposed to calling
    GoodBase<SomeEn tity>() in a class where you don't actually know that the
    type parameter T is "SomeEntity ", which would be wrong).

    Hope that helps.

    Pete

    Comment

    • Peter Duniho

      #3
      Re: Generics and static members

      On Fri, 19 Sep 2008 09:27:25 -0700, Filip Zawada <fzawada@gmail. comwrote:
      [...]
      The question is why can't I call a static method using generic
      parameter?
      By the way, I found these entries on Eric Lippert's blog:





      I haven't had a chance to read through them yet, but given Lippert's place
      in the .NET/C# world, I would expect that these articles do a _much_
      better job of explaining the issue than my short post ever could.

      Pete

      Comment

      • Filip Zawada

        #4
        Re: Generics and static members

        Thank you for the answer, Pete. It was very helpful.
        Now as I know the reasons, it's so obvious.

        Filip

        Comment

        Working...