Passing a class as a method parameter and instantiating it inside the method

Suppose I have the following class

public class SomeClass: {

Class1 obj1 = new Class1 ();
Class2 obj2 = new Class2 ();

.....

void SomeMethod ("Type")

       /* I want to instantiate here an object of Class1 or Class2 depending on the parameter "Type" passed and on some conditions, like:*/

      if (condition)
         "Type"[] inst = new "Type"[5];
         inst[0] = new "Type"();
......
}

I have tried some solutions passing System.Types.Type, using GetType and so on, without success.
I don’t want to instantiate the classes outside because they will be instantiated only under certain conditions.
I want to reuse the method code to any of the available classes without having to rewrite it.
I could pass a string and go through a switch, but since the number of classes is large, the code will get too long.

Look up templates, they should suit your needs.

void SomeMethod<T>()
{
T inst = new T();
}
1 Like

I have to Google this everytime I do it, but if you have the type stored in a variable, it’s Activator.CreateInstance.

void SomeMethod(Type T) {
if (condition) {
T inst = Activator.GetInstance(T);
}
}

Though I’m not sure how you’d create an array of those. I guess you’d just make it an object[ ], since there wouldn’t be any point (code-wise) of having the type be more specific than that, in that context.

On the other hand, if you can, you’d be better off using a generic templated function, as demonstrated by @JC_SummitTech . The above is only best if you need to be able to pick arbitrary types at runtime (a template requires the type be known at compile time).

1 Like

They’re called generic arguments. But you need some common ground if you’re wanting to create new instances. For example - the type passed in would need an empty constructor.

void SomeMethod<T>() where T : new()
{

}
1 Like

I have to thank all three of you, but the answer below did the trick for me.

I had already tried generics, but kept getting an error and so supposed it wasn’t to be instantiated this way. At the end, it was simple and even better than what I wanted, since we can pass more than one class along and by setting an interface for each class, we are able to set the instance’s internal state by using the interface properties.

void SomeMethod<T, U>() where T : TInterface, new() where U : UInterface, new()
{
    T[] arrayT  = new T[5];
    U[] arrayU = new U[5];
    if ( CONDITION ) {
            var attributeOfT = valueT;
            var attributeOfU = valueU;
            arrayT[0] = new T() { Value = valueT}; //"Value" is an interface property.
            arrayU[0] = new U() { Value = valueI};
            ....
    }
}

If someone knows a better way of setting the instances’ properties without the interface, please tell me.

1 Like

Nope - that’s a good use case for interfaces. They’re contractual and you’re basically saying “If I pass something to this method then it contractually needs this property” and the new() constraint gives you a guaranteed way to create an instance.

I’m curious what it is you’re trying to achieve.

I’m building an editor which should write an XML file using System.Xml.Serialization.

Since it’s the first time I’m doing it, I really don’t know if the pattern I’m using is the best one, but it is the one I was able to get working in a convenient way.

I have different classes for the different tree levels on the xml.
< Order >
< Family >
< Gender >
< Species >
…

I have dropdowns on the UI so that the user can make a choice for any of these levels. The user has also the choice of adding a new member. When adding the new member, a method on an editor manager is called (the method which motivated this thread) creating a new instance of the corresponding class and, since the manager keeps reference to the whole xml structure, fits it in the appropriate place in the hierarchy.

The method I wrote above, with T and U, was only an exemplification of what I found out to be possible after you’ve given me the right tip. In my case, I’ll be only passing a single class to the method.

As I said, it is the first time I’m dealing with xml and I don’t know if this is the best design pattern to follow. But it seems to be working fine.

The interface is pretty good, but if you want to avoid it you could pass generic setter functions as arguments and call those. If you know “valueT” is a float for example:

void SomeMethod<T, U>(Action<T, float> tSetter, Action<U, float> uSetter) where T : new() where U : new()
{
    T[] arrayT  = new T[5];
    U[] arrayU = new U[5];
    if ( CONDITION ) {
            var attributeOfT = valueT;
            var attributeOfU = valueU;
            arrayT[0] = new T();
            tSetter(arrayT[0], valueT);
            arrayU[0] = new U();
            uSetter(arrayU[0], valueU);
            ....
    }
}

//Call it like this:
SomeMethod<TheTType, TheUType>((t, val) => t.Value = val, (u, val) => u.Value = val);
//The fields don't have to be named ".Value" this way, you can pass whatever you want, like a function or property

If you don’t know that “valueT” is a float, you can make that a generic argument too:

void SomeMethod<T,U,V,W>(Action<T,V> tSetter, Action<U,W> uSetter) where T : new() where U : new()

//Call it like this:
SomeMethod<Dog, Cat, Bark, Meow>((dog, bark) => dog.SetMyBark(bark), (cat, meow) => cat.Meow = meow);
2 Likes