G
G
Georgy Pelageikin2015-11-23 21:31:11
Mono
Georgy Pelageikin, 2015-11-23 21:31:11

How to bypass the restriction on the absence of parameters in the class constructor of a generic type?

Hello. I am writing a small training raytracer, I want to organize a component-oriented model in it, similar to that used in unity3d. Faced a problem:
There is a class Component . It is simple as an axe:

public class Component
{
  private Component(){}
  
  public Component(SceneObject ownerSceneObject)
  {
    this.ownerSceneObject = ownerSceneObject;
  }
  public readonly SceneObject ownerSceneObject;
}

Those. there is a constructor that is called in only one method of the SceneObject class , the only purpose of which is to remember forever who this instance is bound to. And so that it couldn't be created without this parameter - I don't need spherical components in a vacuum.
And here is the same method in SceneObject :
public void AddComponent<ComponentType>() where ComponentType:Component, new(SceneObject ownerSceneObject)
  {
    components.Add(new ComponentType(this));
  }

And everything would be fine, but the compiler does not allow me to do this - you cannot set a constructor constraint with parameters, only without - just new() . As a result, I cannot call the constructor of the component being added, which throws a null reference exception (because the constructor of the Component-derived class has not been called).
How to get around this limitation?
In other words: how can a generic method be forced to call a constructor with the parameters of this same generic class (in the sense of a class that has a generic type)?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
MonkAlex, 2015-11-23
@MonkAlex

I don't like the very idea of ​​such dependence, but I can't understand WHY.

public class Component
  {
    public Component(SceneObject ownerSceneObject)
    {
      this.ownerSceneObject = ownerSceneObject;
    }
    public readonly SceneObject ownerSceneObject;
  }

  public class SceneObject
  {
    private List<Component> components;
     
    public void AddComponent<T>() where T : Component
    {
      var constructor = typeof(T).GetConstructor(new [] { typeof(SceneObject) });
      var created = constructor.Invoke(new object[] { this }) as T;
      if (created != null)
        this.components.Add(created);
    }

    public SceneObject()
    {
      this.components = new List<Component>();
    }
  }
  }

V
Vitaly Vitrenko, 2015-11-23
@Vestail

You can try that.

public class SceneObject 
{
    //.....
    
    public void AddComponent<ComponentType>(Func<SceneObject, ComponentType> inst) where ComponentType : Component
    {
        components.Add(inst(this));
    }
    
    public static void Main(string[] args)
    {
        SceneObject sObj = new SceneObject();
        sObj.AddComponent((a) => new Component(a) );
      
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question