Method with nested generic types

c# nested generic class
generic method with multiple type parameters c#
c# generic constraints
c# generic method where t interface
c# generic inherit from type
c# generic method parameter
c# generic class constructor with parameters
java generic method return type

I have something along the lines:

public class BaseClass
{

}

public class SimpleDerivedA : BaseClass
{
    public void DoSomething() => Expression.Empty();        
}

public class SimpleDerivedB : BaseClass
{
    public void DoSomething() => Expression.Empty();          
}

public class GenericDerived<T> : BaseClass where T : struct
{
    public T data;
    public void DoSomething<T>(T someParameter) => Expression.Empty();        
}

public void Process<T, X>(T someObject, X someValue = default) where T : BaseClass where X : struct
{
    switch (someObject)
    {
        case SimpleDerivedA a:
            a.DoSomething();
            break;
        case SimpleDerivedB b:
            b.DoSomething();
            break;
        case GenericDerived<X> g:
            X obj = new X();
            g.DoSomething(obj);
            break;
    }

}

Process method works in an ugly way:

    SimpleDerivedA a = new SimpleDerivedA();
    SimpleDerivedB b = new SimpleDerivedB();
    GenericDerived<Vector3> g = new GenericDerived<Vector3>();

    Process(a, new int()); //second parameter is fake, just to be able to 
    call the method
    Process(b, new int()); //second parameter is fake, just to be able to 
    call the method
    Process(g, new Vector3());//second parameter is fake, just to be able to 
    call the method

Ideally I should be able to call Process(a), Process(b), Process(g)

Something like:

public void Process<T>(T someObject)  where T: BaseClass where X: struct
    {
        switch (someObject)
        {
            case SimpleDerivedA a:
                a.DoSomething();
                break;
            case SimpleDerivedB b:
                b.DoSomething();
                break;
            case GenericDerived<X> g:
                var obj = new X();
                g.DoSomething(obj);
                break;
        }

    }

or:

public void Process<T<X>>(T someObject) where T : BaseClass where X : struct
    {
        switch (someObject)
        {
            case SimpleDerivedA a:
                a.DoSomething();
                break;
            case SimpleDerivedB b:
                b.DoSomething();
                break;
            case GenericDerived<X> g:
                var obj = new X();
                g.DoSomething(obj);
                break;
        }

    }

Which obviously don't compile. I need to use it inside an API and the type of GenericDerived<T> won't be known until someone will use it.

The question here is how can I define the method Process so I can use an instance of any of the three derived classes as a parameter but call it only with one parameter like Process(value) not Process(value, fakeValue) or Process<SomeType>(value)?

You should use an overload of your Process function for objects of type GenericDerived, instead of trying to handle everything in one function.

void Process<T>(T someObject) where T : BaseClass {
    switch (someObject)
    {
        case SimpleDerivedA a:
            a.DoSomething();
            break;
        case SimpleDerivedB b:
            b.DoSomething();
            break;
    }
}

void Process<X>(GenericDerived<X> g) where X : struct {
    X obj = new X();
    g.DoSomething(obj);
}

You can then call it like this.

var a = new SimpleDerivedA();
var b = new SimpleDerivedB();
var g = new GenericDerived<Vector3>();

Process(a);
Process(b);
Process(g);

Also consider introducing an interface for objects that can DoSomething, or add a virtual method to BaseClass, so you don't have to type-switch just to call the same method on different objects. This might not be possible since there's a parameter in some derived classes but not others.

C#: Method signatures should not contain nested generic types, A nested type is a type argument that is also a generic type. Calling a method with such a nested type argument requires complicated and confusing code. If the current Type represents a generic type defined in C#, Visual Basic, or C++, its nested types are all generic even if they have no generic parameters of their own. This is not necessarily true of nested types defined in dynamic assemblies or compiled with the Ilasm.exe (IL Assembler) .

public interface IGenericDoSomething
{
  void DoSomethingWithDefault();
}

public class GenericDerived<T> : BaseClass, IGenericDoSomething where T : struct
{
  public T data;
  public void DoSomething<X>(X someParameter) => Console.WriteLine(someParameter);

  void IGenericDoSomething.DoSomethingWithDefault() => DoSomething(default(T)); 
}

  public void Process<T>(T someObject) where T : BaseClass {
    switch (someObject)
    {
      case SimpleDerivedA a:
        a.DoSomething();
        break;
      case SimpleDerivedB b:
        b.DoSomething();
        break;
      case IGenericDoSomething g:
        g.DoSomethingWithDefault();
        break;
    }
  }

CA1006: Do not nest generic types in member signatures, A nested type argument is a type argument that is also a generic type. the rule and the syntax that is required to call the violating method. If the current Type represents a type parameter in the definition of a generic type or generic method, this method searches the nested types of the class constraint. If a nested type is generic, this method returns its generic type definition. This is true even if the enclosing generic type is a closed constructed type.

Add interface to the base class.

interface IProcessable
{
    void DoSomething(params object [] args);
}

public abstract class BaseClass : IProcessable
{
    public abstract void DoSomething(params object[] args);
}

public class GenericDerived<T> : BaseClass where T : struct
{
    public T data;
    public override void DoSomething(params object[] args)
    {
        // optionally you can pass as many arguments as you like
        data = (T)args.First();
    }
}

And then you can pass your object into method like this.

public static void Process(IProcessable obj, params object[] args)
{
    obj.DoSomething(args);
}

Then call it from where ever you need like this

var a =  new SimpleDerivedA();
var b = new SimpleDerivedB();
var c = new GenericDerived<T>();
Process(a);
Process(b);
Process(c, obj /* your struct T */);

Constraints on type parameters, If your generic class or method uses any operation on the generic members beyond simple assignment or calling any methods not supported by  To construct a generic type from the generic type definition for a nested type, call the MakeGenericType method with the array formed by concatenating the type argument arrays of all the enclosing types, beginning with the outermost generic type, and ending with the type argument array of the nested type itself, if it has type parameters of its own.

How to avoid having nested generic in class, I would consider using an interface for Vote instead of generics. And then on your class definitions implement the IVote interface: that implements `IVote` to the method //assuming policyVotes and fundingVotes are type  Generic classes and methods combine reusability, type safety, and efficiency in a way that their non-generic counterparts cannot. Generics are most frequently used with collections and the methods that operate on them. The System.Collections.Generic namespace contains several generic-based collection classes.

Generic Methods (The Java™ Tutorials > Bonus > Generics), This Java tutorial describes generics, full screen mode API, and Java certification related resources. The way to do deal with these problems is to use generic methods. Just like type The same applies to nested generic classes. « Previous​  Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency, a generic method should not be used. It is possible to use both generic methods and wildcards in tandem. Here is the method Collections.copy():

CSE 341 -- Java Generics & Nested Classes, Java Generics & Nested Classes method; Widest.java - generic method example; Wild2a.java - like Wild2, but uses a type parameter rather than a wildcard. You might also notice that the type for the generic list is distinct ([System.Int32]), whereas the type for the non-generic list is generalized. Because the runtime knows the generic List<int> is of type Int32 , it can store the list elements in an underlying integer array in memory, while the non-generic ArrayList has to cast each list element

Comments
  • How about using interface instead?
  • @ just-my-name what should I derive from interface? All classes?
  • I posted it as an answer since it was kind of long for a comment.
  • You should change the name of T for DoSomething in GenericDerived to avoid hiding the outer type parameter (or remove it in case it should be the outer one).
  • Very good idea, overloading the method is the simplest way to do it.
  • I need to pass a parameter to DoSomething<X>(X someParameter) inside Process() method not inside GenericDerived class.
  • In this case you need to know a type of the this parameter in a Process method. Do you know this? Can you show an example?