m.edmondson
m.edmondson

Reputation: 30922

Using Collection Initializer with System.Data.DataTable.Rows

As far as I understand the use of a collection initializer is dependant on two things:

As far as I can tell System.Data.DataTable.Rows satisfies both of the requirements, therefore I would expect I could do this:

DataRow row = _dt.Tables["TABLE"].NewRow();

_dt.Tables["TABLE"].Rows =
{
    row
};

The compiler complains:

Perhaps you could point out my mistake.

Update:

I've just realised my issue is with DataRowCollection which doesn't implement IEnumerable but does have an Add() method. Therefore am I correct in thinking that this doesn't work purely because IEnumerable isn't implemented? If so why can't it be added to the BCL?

Update:

Please see this code that shows you can add to an existing collection with an initializer:

        public class Person
        {
            public Person()
            {
                friends.Add("Paul");
            }

            List<string> friends = new List<string>();

            public List<string> Friends
            {
                get { return friends; }
            }
        }

        Person tom = new Person
        {
            //Adding to an existing collection NOT creating a new one
            Friends = {"Steve", "Jim", "John"}
        };

Upvotes: 0

Views: 1708

Answers (1)

Michael Liu
Michael Liu

Reputation: 55469

Object and collection initializers are only valid in "object creation expressions", which are introduced by the new keyword. From §7.6.10.1 of the C# 4.0 specification:

object-creation-expression:
   new   type   (   argument-listopt   )   object-or-collection-initializeropt
   new   type   object-or-collection-initializer

object-or-collection-initializer:
   object-initializer
   collection-initializer

And from §7.6.10.2:

An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas.

A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property.

So the following is a legal statement that creates a new DataTable and, using a couple of collection initializers, adds items to the embedded Columns and Rows collections:

DataTable table =
    new DataTable  // <-- IMPORTANT
    {
        Columns = { { "Name", typeof(string) } },  // table.Columns.Add("Name", typeof(string));
        Rows = { "John" },                         // table.Rows.Add("John");
    };

In contrast, the following statement is not valid:

table.Rows = { "John" };

Although the expression resembles a collection initializer, it occurs outside the context of an object creation expression (there's no new keyword anywhere), and so the compiler parses the statement as table.Rows = ... instead of table.Rows.Add(...).

In your original example, just call the Add method explicitly:

_dt.Tables["TABLE"].Rows.Add(row);

Upvotes: 2

Related Questions