Search code examples
c#objectgenericsgeneric-programming

Instantiating a new object of T inside of a generic function in C#


I have two models that can both use the function below. I created an Interface that both of these models implement.

In the function below I am looping through the passed in list and using the values in it to create a new version of the list.

public static IList<T> GenericFunction<T>(IList<T> objList) where T : IProduct
{
    // In this function I am doing the following:

    IList<T> retVal = new List<T>();

    foreach (T obj in objList)
    {
        T newObj = (T)Activator.CreateInstance(typeof(T));

        newObj.Price = obj.BasePrice + obj.OldPrice;
        newObj.Description = obj.Name + " " + obj.Description;

        retVal.add(newObj);
    }

    return retVal;
}

The above code is working, but I have a couple of questions:

In order to have a function like the above that works with any model that implements IProduct, doing what I did is my only option right? At first I was thinking I could just simply create a standard function that takes IList<IProduct> as a param and returns IList<IProduct>. But then I ran into the problem of instantiating a new object which led me to creating a Generic Function.

Additionally, can I use an object initializer on newObj to set its properties?

After seeing this StackOverflow post I feel like I should be doing something different.


Solution

  • If you know that IProduct will always have a paramterless constructor, you can achieve this through generic constraints:

    public static IList<T> GenericFunction<T>(IList<T> objList) where T : IProduct, new()
    {
        IList<T> retVal = new List<T>();
    
        foreach (T obj in objList)
        {
            T newObj = new T();
            newObj.Price = obj.BasePrice + obj.OldPrice;
            newObj.Description = obj.Name + " " + obj.Description;
            retVal.Add(newObj);
        }
        return retVal;
    }
    

    new() constrains T such that it must have a parameterless constructor - allowing it to be instantiated via T newObj = new T();.