Initializing list property without "new List" causes NullReferenceException - c#

using System;
using System.Collections.Generic;
class Parent
{
public Child Child { get; set; }
}
class Child
{
public List<string> Strings { get; set; }
}
static class Program
{
static void Main() {
// bad object initialization
var parent = new Parent() {
Child = {
Strings = { "hello", "world" }
}
};
}
}
The above program compiles fine, but crashes at runtime with Object reference not set to an instance of the object.
If you notice in the above snippet, I have omitted new while initializing the child properties.
Obviously the correct way to initialize is:
var parent = new Parent() {
Child = new Child() {
Strings = new List<string> { "hello", "world" }
}
};
My question is why does the C# compiler not complain when it sees the first construct?
Why is the broken initialization valid syntax?
var parent = new Parent() {
Child = {
Strings = { "hello", "world" }
}
};

It's not broken syntax, it's you who uses an object initializer on a property that's simply not instantiated. What you wrote can be expanded to
var parent = new Parent();
parent.Child.Strings = new List<string> { "hello", "world" };
Which throws the NullReferenceException: you're trying to assign the property Strings contained by the property Child while Child is still null.
Using a constructor to instantiate Child first, takes care of this.

There is nothing wrong with the initialisation, but it's trying to initialise objects that doesn't exist.
If the classes have constructors that create the objects, the initialisation works:
class Parent {
public Child Child { get; set; }
public Parent() {
Child = new Child();
}
}
class Child {
public List<string> Strings { get; set; }
public Child() {
Strings = new List<string>();
}
}

You seem to misunderstand what the collection initializer does.
It is a mere syntactic sugar that converts the list in the braces into a series of calls to Add() method that must be defined on the collection object being initialized.
Your = { "hello", "world" } is therefore has the same effect as
.Add("hello");
.Add("world");
Obviously this will fail with a NullReferenceException if the collection is not created.

The second syntax is valid for readonly properties. If you change the code to initialise the Child and Strings properties in the respective constructors, the syntax works.
class Parent
{
public Parent()
{
Child = new Child();
}
public Child Child { get; private set; }
}
class Child
{
public Child()
{
Strings = new List<string>();
}
public List<string> Strings { get; private set; }
}
static class Program
{
static void Main()
{
// works fine now
var parent = new Parent
{
Child =
{
Strings = { "hello", "world" }
}
};
}
}

Referencing a null can`t always be checked for at compile time. Although the compiler sometimes warns of using a variable before it has been assigned. The compiler works correctly. This is a run-time error.

Note that this syntax can cause some unexpected results and hard-to-spot errors:
class Test
{
public List<int> Ids { get; set; } = new List<int> { 1, 2 };
}
var test = new Test { Ids = { 1, 3 } };
foreach (var n in test)
{
Console.WriteLine(n);
}
You might expect the output to be 1,3, but instead it is:
1
2
1
3

Related

Auto-initialized property not using overridden setter [duplicate]

using System;
using System.Collections.Generic;
class Parent
{
public Child Child { get; set; }
}
class Child
{
public List<string> Strings { get; set; }
}
static class Program
{
static void Main() {
// bad object initialization
var parent = new Parent() {
Child = {
Strings = { "hello", "world" }
}
};
}
}
The above program compiles fine, but crashes at runtime with Object reference not set to an instance of the object.
If you notice in the above snippet, I have omitted new while initializing the child properties.
Obviously the correct way to initialize is:
var parent = new Parent() {
Child = new Child() {
Strings = new List<string> { "hello", "world" }
}
};
My question is why does the C# compiler not complain when it sees the first construct?
Why is the broken initialization valid syntax?
var parent = new Parent() {
Child = {
Strings = { "hello", "world" }
}
};
It's not broken syntax, it's you who uses an object initializer on a property that's simply not instantiated. What you wrote can be expanded to
var parent = new Parent();
parent.Child.Strings = new List<string> { "hello", "world" };
Which throws the NullReferenceException: you're trying to assign the property Strings contained by the property Child while Child is still null.
Using a constructor to instantiate Child first, takes care of this.
There is nothing wrong with the initialisation, but it's trying to initialise objects that doesn't exist.
If the classes have constructors that create the objects, the initialisation works:
class Parent {
public Child Child { get; set; }
public Parent() {
Child = new Child();
}
}
class Child {
public List<string> Strings { get; set; }
public Child() {
Strings = new List<string>();
}
}
You seem to misunderstand what the collection initializer does.
It is a mere syntactic sugar that converts the list in the braces into a series of calls to Add() method that must be defined on the collection object being initialized.
Your = { "hello", "world" } is therefore has the same effect as
.Add("hello");
.Add("world");
Obviously this will fail with a NullReferenceException if the collection is not created.
The second syntax is valid for readonly properties. If you change the code to initialise the Child and Strings properties in the respective constructors, the syntax works.
class Parent
{
public Parent()
{
Child = new Child();
}
public Child Child { get; private set; }
}
class Child
{
public Child()
{
Strings = new List<string>();
}
public List<string> Strings { get; private set; }
}
static class Program
{
static void Main()
{
// works fine now
var parent = new Parent
{
Child =
{
Strings = { "hello", "world" }
}
};
}
}
Referencing a null can`t always be checked for at compile time. Although the compiler sometimes warns of using a variable before it has been assigned. The compiler works correctly. This is a run-time error.
Note that this syntax can cause some unexpected results and hard-to-spot errors:
class Test
{
public List<int> Ids { get; set; } = new List<int> { 1, 2 };
}
var test = new Test { Ids = { 1, 3 } };
foreach (var n in test)
{
Console.WriteLine(n);
}
You might expect the output to be 1,3, but instead it is:
1
2
1
3

How to make a list property writable in object initializer but read only in other places?

Consider the following code snippet that does not compile.
class Class
{
public double Value { get; set; }
public int Frequency { get; set; }
}
class BoxAndWhisker
{
private readonly List<Class> _classes = new List<Class>();
public BoxAndWhisker()
{
Classes = _classes.AsReadOnly();
}
public IReadOnlyList<Class> Classes { get; }
}
class Program
{
static void Main(string[] args)
{
BoxAndWhisker baw = new BoxAndWhisker
{
Classes =
{
new Class{ Value=1,Frequency=20},
new Class{Value=2,Frequency=10}
}
};
}
}
I want the property Classes to be read only right after baw is instatiated. How to do so? In other words, Classes must be writable in object initializer but read only in other places.
Edit
I prefer object initializer to parameterized constructor.
Why not pass Classes via constructor? E.g.
class BoxAndWhisker {
public BoxAndWhisker(params Class[] items) {
Classes = null != items
? new List<Class>(items).AsReadOnly()
: throw new ArgumentNullException(nameof(items));
}
public IReadOnlyList<Class> Classes { get; }
}
Then
static void Main(string[] args)
{
BoxAndWhisker baw = new BoxAndWhisker(
new Class { Value = 1, Frequency = 20 },
new Class { Value = 2, Frequency = 10 }
);
...
}
Remove the
set;
From the properties within
Class
And make the Class have a Constructor which sets the initial values of the Properties, therefore they cannot be overwrote / changed
The "object initializer" syntax in C# has no semantic difference compared to a property value assignment.
You can read in the docs:
The object initializers syntax allows you to create an instance, and after that it assigns the newly created object, with its assigned properties, to the variable in the assignment.
So this:
var foo = new Bar { Baz = "baz" };
is completely equivalent to:
var temp = new Bar();
temp.Baz = "baz";
var foo = temp;
So you cannot restrict the property assignment the way you want.
The only solution is to use a constructor as proposed in the other answers.
You pass the IList<Class> instance to the BoxAndWhisker constructor and maintain a backing IReadOnlyList<Class> property
class BoxAndWhisker
{
public BoxAndWhisker(IList<Class> classes)
{
if (classes == null)
throw new ArgumentNullException(nameof(classes));
Classes = new ReadOnlyCollection<Class>(classes);
}
public IReadOnlyList<Class> Classes { get; }
}
The usage example
BoxAndWhisker baw = new BoxAndWhisker(new List<Class>
{
new Class {Value = 1, Frequency = 20},
new Class {Value = 2, Frequency = 10}
});

Setting property inside method [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
Is something like the following possible or do you have to return the list and assign it afterwards? I get object reference not set to instance of an object.
public class MyCollection
{
public List<SomeObject> Collection { get; set; }
public List<SomeObject> CreateCollection()
{
// Is there a way to set the Collection property from here???
this.Collection.Add(new SomeObject()
{
// properties
});
}
}
...
MyCollection collection = new MyCollection();
collection.CreateCollection();
Yes, you can use an object initializer:
public List<SomeObject> CreateCollection()
{
// You may want to initialize this.Collection somehere, ie: here
this.Collection = new List<SomeObject>();
this.Collection.Add(new SomeObject
{
// This allows you to initialize the properties
Collection = this.Collection
});
return this.Collection;
}
Note that this will still potentially have an issue - you are never initializing this.Collection in any code you're displaying. You will need to initialize it to a proper collection in your constructor or via some other mechanism.
It is also an odd choice to have a "Create" method that initializes the local variable and returns a List<T>. Typically, you'd do one or the other. A more common approach would be to place this code within the constructor:
public class MyCollection
{
public IList<SomeObject> Collection { get; private set; } // The setter would typically be private, and can be IList<T>!
public MyCollection()
{
this.Collection = new List<SomeObject>();
this.Collection.Add(new SomeObject
{
Collection = this.Collection
});
}
}
You could then use it via:
MyCollection collection = new MyCollection();
var object = collection.Collection.First(); // Get the first element
That being said, in general, there is no real reason to make a custom class for a collection like this in most cases. Just using a List<SomeObject> directly is typically sufficient.
It's completely possible - you just have to instantiate it first, before you can use it:
public List<SomeObject> CreateCollection()
{
this.Collection = new List<SomeObject>(); // this creates a new list - the default if you just define a list but don't create it is for it to remain null
this.Collection.Add(new SomeObject()
{
// whatever
});
}
Of course, as pointed out in a comment, if you want that function to return a list, it would have to actually return the list. Presumably you mean public void CreateCollection(), though, since that was your question, whether you actually had to return a list (answer: no).
You must initialize this.Collection before adding elements into it.
public List<SomeObject> CreateCollection()
{
this.Collection = new List<SomeObject>();
this.Collection.Add(new SomeObject()
{
// properties
});
}
You can use a list initializer in this case:
public class Person
{
public string Name { get; set; }
public string Firstname { get; set; }
}
class Program
{
public static List<Person> Collection { get; set; }
public static List<Person> CreateCollection()
{
return new List<Person>()
{
new Person() { Name = "Demo", Firstname = "Demo1"},
new Person() { Name = "Demo", Firstname = "Demo1"},
};
}
static void Main(string[] args)
{
Collection = CreateCollection();
}
}

Creating a List of Lists in C#

I seem to be having some trouble wrapping my head around the idea of a Generic List of Generic Lists in C#. I think the problem stems form the use of the <T> argument, which I have no prior experience playing with. Could someone provide a short example of declaring a class which is a List, that therein contains another List, but where the type of the object contained therein is not immediately known?
I've been reading through the MS documentation on Generics, and I am not immediately sure if I can declare a List<List<T>>, nor how exactly to pass the <T> parameter to the inside list.
Edit: Adding information
Would declaring a List<List<T>> be considered legal here? In case you are wondering, I am building a class that allows me to use a ulong as the indexer, and (hopefully) steps around the nasty 2GB limit of .Net by maintaining a List of Lists.
public class DynamicList64<T>
{
private List<List<T>> data = new List<List<T>>();
private ulong capacity = 0;
private const int maxnumberOfItemsPerList = Int32.MaxValue;
public DynamicList64()
{
data = new List<List<T>>();
}
A quick example:
List<List<string>> myList = new List<List<string>>();
myList.Add(new List<string> { "a", "b" });
myList.Add(new List<string> { "c", "d", "e" });
myList.Add(new List<string> { "qwerty", "asdf", "zxcv" });
myList.Add(new List<string> { "a", "b" });
// To iterate over it.
foreach (List<string> subList in myList)
{
foreach (string item in subList)
{
Console.WriteLine(item);
}
}
Is that what you were looking for? Or are you trying to create a new class that extends List<T> that has a member that is a `List'?
or this example, just to make it more visible:
public class CustomerListList : List<CustomerList> { }
public class CustomerList : List<Customer> { }
public class Customer
{
public int ID { get; set; }
public string SomethingWithText { get; set; }
}
and you can keep it going. to the infinity and beyond !
A list of lists would essentially represent a tree structure, where each branch would constitute the same type as its parent, and its leaf nodes would represent values.
Implementation
public sealed class TreeList<T> : List<TreeList<T>>
{
public List<T> Values { get; } = new List<T>();
public TreeList<T> this[int index]
{
get
{
while (index > Count - 1)
{
Branch();
}
return base[index];
}
}
public TreeList<T> Branch()
{
TreeList<T> result = new TreeList<T>();
Add(result);
return result;
}
}
Example
internal static class Program
{
public static void Main()
{
// Create the root element...
TreeList<string> treeList = new TreeList<string>();
// You can add branches the old-fashioned way...
treeList.Add(new TreeList<string>());
// Add leaf node values to your first branch...
treeList[0].Values.Add("Hello, World!");
treeList[0].Values.Add("Goodbye, World!");
// You can create new branches from any branch like this...
// Note: You could also chain branch statements; i.e. treeList.Branch().Branch().Branch()
TreeList<string> branch2 = treeList.Branch();
// Add leaf node values to your second branch...
branch2.Values.Add("Alice");
branch2.Values.Add("Bob");
// You can also create branches until you reach the desired branch index...
// The TreeList indexer will loop until the desired index has been created, and then return it.
treeList[7].Values.Add("Alpha");
treeList[7].Values.Add("Bravo");
treeList[7].Values.Add("Charlie");
// How many branches does the root have?
Console.WriteLine($"Treelist branches: {treeList.Count}");
// What's at branch 0's values?
foreach (string value in treeList[0].Values)
{
Console.WriteLine(value);
}
// What's at branch 1's values?
foreach (string value in treeList[1].Values)
{
Console.WriteLine(value);
}
// What's at branch 7's values?
foreach (string value in treeList[7].Values)
{
Console.WriteLine(value);
}
}
}
Now, whether you should implement something like this is another matter. Extending List<T> isn't recommended: Why not inherit from List<T>?
public class ListOfLists<T> : List<List<T>>
{
}
var myList = new ListOfLists<string>();
I have the following code
public class ChildClass
{
public string FieldName { get; set; }
public string Value { get; set; }
public string StatusClass { get; set; }
public string StatusMessage { get; set; }
}
Creating a list of list obj is as follows
List<List<ChildClass>> obj = new List<List<ChildClass>>();
Look a direct example here:
public partial class Form1 : Form
{
List<List<Label>> txtList;
List<List<int>> num;
public Form1()
{
InitializeComponent();
txtList = new List< List<Label> >() {
new List<Label> { label1, label2, label3 },
new List<Label> { label4, label5, label6 },
new List<Label> { label7, label8, label9 }
};
num = new List<List<int>>() { new List<int>() { 1, 2 }, new List<int>() { 3, 4 } };
}
}
you should not use Nested List in List.
List<List<T>>
is not legal, even if T were a defined type.
https://msdn.microsoft.com/en-us/library/ms182144.aspx

Why IEnumerable<T> becomes empty after adding elements to a collection?

I have an IEnumerable<T> when I iterate through it and add it's element to a list it becomes empty?
Is there generally anything wrong about what I expect from the code?
public class Apple
{
private ICollection<Fruit> _fruits = new List<Fruit>();
public void AddFruits(IEnumerable<Fruit> fruits)
{
if (fruits == null) throw new ArgumentNullException("fruits");
foreach (var fruit in fruits)
{
_fruits.Add(fruit);
}
}
}
The caller code:
public void AddFruits(IEnumerable<Fruit> fruitsToAdd)
{
foreach (var apple in apples)
{
// Here fruitsToAdd has elements, fruitsToAdd.ToList() has two fruits.
apple.AddFruits(fruitsToAdd);
// Here fruitsToAdd has NO element!!, fruitsToAdd.ToList() is empty!
// next iteration will not add any fruit to next apple since fruitsToAdd is empty.
}
}
Update
The ToList() solved the problem. The root of the problem was that the caller to AddFruits(IEnumerable fruitsToAdd) send fruitsToAdd that was like.
fruitsToAdd = obj.Fruits.Except(apples.Fruits);
Each time IEnumerable fruitsToAdd was Rest it run above statement. Which at next iteration run Except and thereby returned no fruits.
The right way is fruitsToAdd = obj.Fruits.Except(apples.Fruits).ToList(); Since we want one evaluation.
Ok, try this:
public void AddFruits(IEnumerable<Fruit> fruitsToAdd)
{
var fruitsToAddCopy = fruitsToAdd.ToList(); // add just this line
foreach (var apple in apples)
{
apple.AddFruits(fruitsToAddCopy); // and change this
}
}
Without knowing the origin of your fruitsToAdd it's impossible to say more. Some IEnumerable<> can't be re-used. Others can.
I modified your code to get it to compile and wrote a test. Your list does not become empty after copying it's elements into the apples.
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ClassLibrary3
{
[TestClass]
public class Class1
{
[TestMethod]
public void test()
{
var fruits = new List<Fruit> {new Fruit(), new Fruit(), new Fruit()};
var lists = AddFruits(fruits);
Assert.IsTrue(fruits.Count == 3);
}
public List<Apple> AddFruits(IEnumerable<Fruit> fruitsToAdd)
{
var apples = new List<Apple>
{
new Apple(),
new Apple()
};
foreach (var apple in apples)
{
apple.AddFruits(fruitsToAdd);
}
return apples;
}
}
public class Fruit
{
}
public class Apple
{
private ICollection<Fruit> _fruits = new List<Fruit>();
public void AddFruits(IEnumerable<Fruit> fruits)
{
if (fruits == null) throw new ArgumentNullException("fruits");
foreach (var fruit in fruits)
{
_fruits.Add(fruit);
}
}
}
}
The code in your question shouldn't exhibit such behavior, so I am presuming you tried to simplify it, but removed a lot of functionality from it.
What looks a bit suspicious is that your _fruits field is of type ICollection<T>. This interface is often used with custom collection implementations. Is it possible that, in the actual code, this field isn't instantiated with a List<T>, but rather with a custom implementation of that interface?
If you have a custom collection implementation, then it is perfectly possible for its Add method to do weird stuff (like removing an item from its previous "parent" collection before adding it to its new "parent"). Tree collections often do such things to simplify moving nodes around.
[Edit]
I am aware that this is not OPs actual problem, but I will nevertheless add an example to demonstrate that a custom collection implementation can in fact modify the input collection when its members are added to a different collection.
Let's say the Fruit class looks like this:
partial class Fruit
{
private ICollection<Fruit> _children;
private Fruit _parent;
public String Name { get; set; }
public Fruit()
{
_children = new FruitCollection(this);
}
public void AddFruits(IEnumerable<Fruit> fruits)
{
foreach (Fruit f in fruits)
_children.Add(f);
}
public int NumberOfChildren
{
get { return _children.Count; }
}
public IEnumerable<Fruit> GetFruits()
{
return _children.ToList();
}
}
And there is a custom collection defined as:
partial class Fruit
{
public class FruitCollection : Collection<Fruit>
{
private readonly Fruit _parent;
public FruitCollection(Fruit parent)
{
_parent = parent;
}
protected override void InsertItem(int index, Fruit item)
{
// item already has a parent?
if (item._parent != null)
{
// remove it from previous parent
item._parent._children.Remove(item);
}
// set the new parent
item._parent = _parent;
base.InsertItem(index, item);
}
// other methods should be overriden in a similar way
}
}
Then the following program:
static void Main(string[] args)
{
List<Fruit> abc = new List<Fruit>()
{
new Fruit() { Name = "a" },
new Fruit() { Name = "b" },
new Fruit() { Name = "c" }
};
Fruit apple = new Fruit() { Name = "apple" };
apple.AddFruits(abc);
Console.WriteLine("{0} has {1} children", apple.Name, apple.NumberOfChildren);
// now try to add apples's children to
// each of the following fruits
List<Fruit> def = new List<Fruit>()
{
new Fruit() { Name = "d" },
new Fruit() { Name = "e" },
new Fruit() { Name = "f" }
};
foreach (Fruit f in def)
{
f.AddFruits(apple.GetFruits());
Console.WriteLine("{0} has {1} children", f.Name, f.NumberOfChildren);
}
Console.Read();
}
Would print:
apple has 3 children
d has 3 children
e has 0 children
f has 0 children
Because apple.GetFruits() will return 0 after the first iteration.
By looking at the custom collection's source, it is hard to realize that _children.Add(f) in AddFruits in fact modifies the fruits previous parent collection.

Categories

Resources