Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

c# - List<int> test = {1, 2, 3} - is it a feature or a bug?

As you know, it is not allowed to use the Array-initialisation syntax with Lists. It will give a compile-time error. Example:

List<int> test = { 1, 2, 3} 
// At compilation the following error is shown:
// Can only use array initializer expressions to assign to array types. 

However today I did the following (very simplified):

class Test
{
     public List<int> Field;
}

List<Test> list = new List<Test>
{
    new Test { Field = { 1, 2, 3 } }
};

The code above compiles just fine, but when run it will give a "Object references is not set to an object" run-time error.

I would expect that code to give a compile-time error. My question to you is: Why doesn't it, and are there any good reasons for when such a scenario would run correctly?

This has been tested using .NET 3.5, both .Net and Mono compilers.

Cheers.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think this is a by-design behavior. The Test = { 1, 2, 3 } is compiled into code that calls Add method of the list stored in the Test field.

The reason why you're getting NullReferenceException is that Test is null. If you initialize the Test field to a new list, then the code will work:

class Test {    
  public List<int> Field = new List<int>(); 
}  

// Calls 'Add' method three times to add items to 'Field' list
var t = new Test { Field = { 1, 2, 3 } };

It is quite logical - if you write new List<int> { ... } then it creates a new instance of list. If you don't add object construction, it will use the existing instance (or null). As far as I can see, the C# spec doesn't contain any explicit translation rule that would match this scenario, but it gives an example (see Section 7.6.10.3):

A List<Contact> can be created and initialized as follows:

var contacts = new List<Contact> {
    new Contact {
        Name = "Chris Smith",
        PhoneNumbers = { "206-555-0101", "425-882-8080" }
    },
    new Contact {
        Name = "Bob Harris",
        PhoneNumbers = { "650-555-0199" }
    }
};

which has the same effect as

var contacts = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
contacts.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
contacts.Add(__c2);

where __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...