Search code examples
c#genericsstatic-methods

static method with generics


In java I have a class:

static public class PCB_Node<T extends PCB_Node<T>> implements Iterable<T> {
    public T parent;
    public T first_child;
    public T next_brother;
    
    public Iterator<T> iterator() {
        return get_iterator((T)this);
    }

}


static public <T extends PCB_Node<T>> Iterator<T> get_iterator(T e) {
    ...
}

I attempt to do port this to c#, in which I have very little experience.

I defined the class like this:

public class PCB_Node<T> where T : PCB_Node<T>, IEnumerable<T> {
    public T parent;
    public T first_child;
    public T next_brother;

    public IEnumerator<T> GetEnumerator() {
        return get_iterator((T)this); // << not sure about this, but that also depends on if it is possible
    }
}

I have problems with doing the following java line in c#: static public <T extends PCB_Node<T>> Iterator<T> get_iterator(T e) {. And I'm not sure if it's even possible, cause so far, I can't find anything about it. I know I can implement GetEnumerator in the class itself instead of redirecting it to some static method, but I prefer it this way.

I guess this is what I want:

static public IEnumerable<T> get_iterator(T e) where T : PCB_Node<T> {

Is something like that possible?


Solution

  • Firstly, your class declaration is not correct.

    Here you are saying that T must be a PCB_Node<T> and implement IEnumerable<T>:

    public class PCB_Node<T> where T : PCB_Node<T>, IEnumerable<T>
    

    Whereas you want PCB_Node<T> to implement IEnumerable<T>:

    public class PCB_Node<T> : IEnumerable<T> where T : PCB_Node<T>
    

    Secondly, this could cause you problems:

    get_iterator((T)this)
    

    Although T is a PCB_Node<T>, this, being of type PCB_Node<T> is not necessarily a T, which would lead to a runtime exception in this example:

    class DerivedNode : PCB_Node<DerivedNode> { }
    
    var node = new PCB_Node<DerivedNode>();
    var enumerator = node.GetEnumerator(); // InvalidCastException
    

    If you want to offload the implementation of GetEnumerator to a static method, you would need to declare it like this:

    public class PCB_Node<T> : IEnumerable<T> where T : PCB_Node<T>
    {
        public IEnumerator<T> GetEnumerator() => get_iterator(this);
    
        public static IEnumerator<T> get_iterator(PCB_Node<T> node)
        {
            //...
        }
    }
    

    If get_iterator is declared in another class, you would need to reapply the constraint:

    public class AnotherClass
    {
        public static IEnumerator<T> get_iterator<T>(PCB_Node<T> node) where T : PCB_Node<T>
        {
            //...
        }
    }
    

    Then call like this:

    public IEnumerator<T> GetEnumerator() => AnotherClass.get_iterator(this);