2

I want to build a generic Observable Collection, that load values from the database to its items. In order to assign the values to the property of the item, I want to create an instance of the object. However, I get an error for the Activator.CreateInstance Command: "'T' is a type, which is not valid in the given context"

public class ListBase<T> : ObservableCollection<T>
{
    private DbTable tab;


    public ListBase()
    {
        tab = DbCatalog.Tables.Where(x => x.ModelObjectType == typeof(T).Name).First();

        LoadValues();
    }

    private void LoadValues()
    {

        foreach (DataRow r in tab.GetValues.Rows)
        {
            T o = (T)Activator.CreateInstance(T); //<-- The (T) at the end throws the error

            var p = o.GetType().GetProperty("xyz_property");

            if (p.PropertyType == typeof(int))
            {
                p.SetValue(o, Convert.ToInt32(r["xyz_fromDB"]));
            }

        }
    }

}
2
  • 2
    Try CreateInstance(typeof(T)) Commented Dec 23, 2017 at 11:35
  • Works fine! Thanks! Commented Dec 23, 2017 at 11:37

2 Answers 2

10

There's no need to use Activator.CreateInstance, the correct way to do this is to new it up like you would any object - but this requires a new constraint:

public class ListBase<T> : ObservableCollection<T> where T : new()
{

}

And now you can simply do this:

T o = new T();
Sign up to request clarification or add additional context in comments.

6 Comments

I havent tried it, but wouldn't this create an instance of the collection instead of a new item? How would I assingn the values to to the object?
No, it's just creating a new T. The rest of the code stays the same.
The line T o = new T(); gives me the error "C# Cannot create an instance of the variable type 'T' because it does not have the new() constraint"
Like I said in my answer, add the new constraint - at the end of the first line.
Firslty, you can see at a glance that you are creating a new object rather than the slightly more obscure CreateInstance. Also, it forces the new constraint which means T requires a parameterless constructor and will not compile otherwise. With the previous method, you are vulnerable to runtime errors.
|
5

You should use: CreateInstance(typeof(T)), typeof returns an object of class System.Type which will work.

There is a difference in C# between a 'Generic' type T and an instance of System.Type. Activator.CreateInstance requires the latter.


Edit: You should generally use DavidG's method, it is cleaner. You can use the Activator when:

  • You can't add a generic constraint for some reason.
  • You want to pass arguments to the constructor. (the new() constraint implies a parameterless constructor, with the Activator you can pass parameters.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.