FooBar
FooBar

Reputation: 142

out parameters in object initializer during anonymous instantiation

If I have an object containing a public int property (public accessors), how can I parse a string to int when initializing this property at instantiation ?

// Given initialized DataTable table;
// Given public int IntProperty {get; set;} in public class MyObject    
table.Rows.Select(row => new MyObject 
{
   int.TryParse(row["stringValue"], IntProperty), // MyObject.IntProperty is unknown here
   IntProperty = int.TryParse(row["stringValue"], ... ) // IntProperty is known but what about the out int result argument of Int32.TryParse ?
});

EDIT : I could do this but want to know if there is a way to do it directly inside object initializer :

table.Rows.Select(row => {
    int.TryParse(row["stringValue"], out int intProperty);
    return new MyObject 
    {
       IntProperty = intProperty;
    }
});

Upvotes: 4

Views: 834

Answers (5)

derpirscher
derpirscher

Reputation: 17400

If you are sure, your stringvalue will always be parseable to int you can use int.Parse()

Otherwise, you will also have to handle a failed parsing. You can do like this:

  • define the out parameter in the outer scope
  • use it in an assignment in case of successful parsing

WARNING This will fail, if you traverse your list in parallel!

    List<string> list = new List<string>{"1", "2", "3"}; 
    int i = 0;
    var ilist = list.Select(x => new MyObject {
        IntProperty = int.TryParse(x, out i) ? i : 0
    });

EDIT With inline declarations from VS2107 you can even do it without the variable from the outer scope

    List<string> list = new List<string>{"1", "2", "3"}; 
    var ilist = list.Select(x => new MyObject {
        IntProperty = int.TryParse(x, out int i) ? i : 0
    });

Upvotes: 1

Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34234

No, it is not possible to use out argument with object initializer.

You could just use Int.Parse if you expect this row to always contain an integer, and then catch an exception. I would say that this the correct way to do this.

try
{
    table.Rows.Select(row => new MyObject 
    {
       IntProperty = int.Parse(row["stringValue"]) 
    });
catch (FormatException)
{
    // handle format exception    
}

If you still want to use Int.TryParse, then you would need to use body statement:

table.Rows.Select(row => {
    bool parseResult = int.TryParse(row["stringValue"], out int x); 
    // TODO: handle parseResult! do not ignore it     
    return new MyObject 
    {
        IntProperty = x
    }
});

Upvotes: 0

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37050

I strongly agree Jeroen Mostert. Instead of "squeezing everything into an object-initializer", make your code readable and easy to unserstand. Than it´ll probably compile without problems:

var result = new List<MyObject>();
foreach(var row in table.Rows)
{
    var instance = new MyObject();
    int value;
    if(int.TryParse(row["stringValue"], out value)
        instance.IntProperty = value;
    result.Add(instance);
}

In C#7 you can also simplify this a bit to the following:

var instance = new MyObject();
if(int.TryParse(row["stringValue"], out int value)
    instance.IntProperty = value;
result.Add(instance);

Upvotes: 2

Alen Genzić
Alen Genzić

Reputation: 1418

There is no way to do it in the way you are trying to do this, you need an intermediate variable to store the out value:

// Given initialized DataTable table;
// Given public int IntProperty {get; set;} in public class MyObject    
table.Rows.Select((row) => 
{
    if(int.TryParse(row["stringValue"], out int intValue)){
        return new MyObject 
        {
            IntProperty = intValue
        };
    }
    else {
        //do error handling
    }
});

Upvotes: 0

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101701

You will have to use out variable to assign it back to IntProperty, so I reckon there is no way to do it one statement inside of object initializer.

Either use int.Parse or wrap the call to int.TryParse in another utility method you create that returns in instead of bool and call it instead.

Upvotes: 0

Related Questions