匿名实例化期间对象初始值设定项中的 out 参数

out parameters in object initializer during anonymous instantiation

如果我有一个包含 public int 属性(public 访问器)的对象,在实例化时初始化此 属性 时如何将字符串解析为 int ?

// 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 ?
});

编辑:我可以这样做,但想知道是否有办法直接在对象初始值设定项中执行此操作:

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

您将不得不使用 out 变量将其分配回 IntProperty,所以我认为没有办法在对象初始值设定项中用一个语句来完成它。

使用 int.Parse 或将对 int.TryParse 的调用包装在您创建的另一个实用方法中 returns 而不是 bool 并调用它。

不,不可能将 out 参数与对象初始值设定项一起使用。

如果您希望此行始终包含一个整数,则可以只使用 Int.Parse,然后捕获异常。我会说这是执行此操作的正确方法。

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

如果你仍然想使用Int.TryParse,那么你需要使用正文语句:

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
    }
});

无法按照您尝试的方式进行操作,您需要一个中间变量来存储输出值:

// 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
    }
});

如果您确定,您的字符串值将始终可解析为 int 您可以使用 int.Parse()

否则,您还必须处理解析失败。你可以这样做:

  • 在外部作用域中定义 out 参数
  • 在解析成功的情况下在赋值中使用它

警告 如果您并行遍历列表,这将失败!

    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 使用 VS2107 的内联声明,您甚至可以在没有外部作用域的变量的情况下做到这一点

    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
    });

我非常同意 Jeroen Mostert。而不是 "squeezing everything into an object-initializer",使您的代码可读且易于理解。它可能会毫无问题地编译:

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);
}

在 C#7 中,您还可以将其简化为以下内容:

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