C Sharper
C Sharper

Reputation: 8626

Cannot implicitly convert type void to List

I have below class structure:

class Child
{
    public List<ParentData> ParentData { get; set; }
}

class ParentData
{
    public string FatherName {get;set;}
    public string MotherName {get;set;}
    public List<GrandParentData> GrandParentData{ get; set; }
}

class GrandParentData
{
    public string GrandFatherName {get;set;}
    public string GrandMotherName {get;set;}
}

When I am trying to fill this:

foreach (var item in res)
{
    obj.StoryData.Add(
        new StoryData
        {
            FatherName = item.FatherName,
            MotherName = item.Description,                                                                        
            GrandParentData = new List<GrandParentData().Add(
                new GrandParentData 
                { 
                    GrandFatherName = "",
                    GrandMotherName = ""
                }
            );
        }                            
    );
}

This is giving me error when I am trying to add data to GrandParentList List:

Cannot implicitly convert type void to List

Do I need to change my class structure? What edits should I make to my code?

Upvotes: 2

Views: 5569

Answers (4)

Mrinal Kamboj
Mrinal Kamboj

Reputation: 11478

Source of Issue is this piece of code:

GrandParentData=new List<GrandParentData().Add(
new GrandParentData { GrandFatherName = "",GrandMotherName =""}

Why ?

GrandParentData is of type List<GrandParentData> and List<GrandParentData>.Add method returns void, so its simply saying you cannot map a List<GrandParentData> to void return and that's fair. Following is the implementation of the List<T>.Add

 public void Add(T item) {
            if (_size == _items.Length) EnsureCapacity(_size + 1);
            _items[_size++] = item;
            _version++;
        }

Check here

Solution would be:

As listed in other answers above where you do object addition as part of the List creation, in fact you may simply do:

GrandParentData = new List<GrandParentData() { new GrandParentData()}

And assign the default values in the constructor as follows:

class GrandParentData
{
    public string GrandFatherName {get;set;}
    public string GrandMotherName {get;set;}

    public GrandParentData()
    {
       GrandFatherName = "";
       GrandMotherName = "";

    }
}

On another note another surprising point related to model design, there's a model named GrandParentData and you have a public List<GrandParentData> GrandParentData{ get; set; }, this in general is confusing, ideally use a suffix to show that its a collection

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500675

So this part is the problem:

GrandParentData=new List<GrandParentData().Add(
    new GrandParentData { GrandFatherName = "",GrandMotherName =""});

There are three problems here:

  • You're not closing the type argument
  • You've got a semi-colon at the end, despite this being part of an object initializer
  • You're calling the Add method, which returns void - hence the compile-time error

As further explanation for the last part, ignoring the fact that you're in an object initializer, your code is equivalent to trying to write something like:

List<int> list = new List<int>().Add(1);

That's invalid because new List<int>().Add(1) doesn't return anything. To use Add like that explicitly, you'd need to declare the variable separately:

List<int> list = new List<int>();
list.Add(1);

That doesn't work within an object initializer of course, as you need to provide a single expression to set the property.

The solution is to use a collection initializer instead. In our simple case that would be:

List<int> list = new List<int> { 1 };

In your more complex case, you'd do this:

GrandParentData = new List<GrandParentData>
{ 
    new GrandParentData { GrandFatherName = "", GrandMotherName = "" }
}

Alternatively, you could change GrandParentData to be a read-only property, but have it already initialized, like this:

public List<GrandParentData> GrandParentData { get; } =
    new  List<GrandParentData>();

Then you could just write:

GrandParentData =
{ 
    new GrandParentData { GrandFatherName = "", GrandMotherName = "" }
}

... and the new GrandParentData would be added to the existing collection.

Upvotes: 7

Gilad Green
Gilad Green

Reputation: 37299

You cannot create a new list and then call Add on it in this manner (of assigning value)

  • Instead of:

    GrandParentData = new List<GrandParentData>().Add(...)
    
  • Write (using collection initializer syntax):

    GrandParentData = new List<GrandParentData> { new GrandParentData { ... } }
    

Reason for specific error is that Add is a void method, and therefore when you try to assign the result to the property you get the error.

Check the following code and see that first line is okay but second gives error:

new List<string>().Add("text");
var list = new List<string>().Add("text");

Though first line actually works and does not give an error it has now sense in it as you have no reference to that collection and the initialized list will be collected by the GC

Upvotes: 6

Patrick Hofman
Patrick Hofman

Reputation: 156978

You are trying to assign the result of the Add method (a void) to the variable. That is not possible. void can't be assigned to a variable.

Here come collection initializers to the rescue:

GrandParentData = new List<GrandParentData()
                  { new GrandParentData { GrandFatherName = "",GrandMotherName =""}
                  }

Upvotes: 2

Related Questions