2

我是 linq 的新手,这不断出现在一个空卷字段上。该文件是不可预测的,它会发生,所以我想在有异常的地方放一个 0。有什么快速简单的方法吗?

     var qry =
            from line in File.ReadAllLines("C:\\temp\\T.txt")
            let myRecX = line.Split(',')
            select new myRec()

            {

               price =   Convert.ToDecimal( myRecX[0].Replace("price =  ", "")) ,
               volume = Convert.ToInt32(myRecX[1].Replace("volume =", "")),
                dTime = Convert.ToDateTime( myRecX[2].Replace("timestamp =", ""))

            };
4

3 回答 3

4

如果您想在传入数据为null、空或完全由空白字符组成时使用默认值,您可以这样做:

volume = string.IsNullOrWhitesplace(myRecX[1])
       ? defaultVolume // <<== You can use any constant here
       : Convert.ToInt32(myRecX[1].Replace("volume =", ""))

但是,这是实现您需要的“快速而肮脏”的方式,因为每个命名参数的位置仍然是硬编码的。一种更健壮的方法是编写一个迷你解析器,它关注文件中指定的属性名称,而不是用空字符串替换它们。

于 2013-03-22T18:20:31.510 回答
0

你可以使用这样的东西,它提供了一种表达方式来写你想要的东西:

static TOutput Convert<TInput, TOutput>(
    TInput value,
    params Func<TInput, TOutput>[] options)
{
    foreach (var option in options) {
        try { return option(value); }
        catch { }
    }

    throw new InvalidOperationException("No option succeeded.");
}

像这样使用:

select new myRec()
{
   price = Convert(myRecX[0].Replace("price =  ", ""),
                   input => Convert.ToDecimal(input),
                   or => 0M),
   ...
};

函数间接和隐式数组构造可能会导致轻微的性能损失,但它为您提供了一个很好的语法,用于指定许多可能的转换,其中第一个成功的转换被采用。

于 2013-03-22T18:35:19.043 回答
0

我认为这里有一个问题超出了使用Linq.

一般来说,在清理文件数据之前对其进行操作是不好的做法。

如果以下问题是关于文件名(而不是它的内容)的,那么这是理解清理输入概念的一个很好的起点:

C# 清理文件名

毕竟你自己告诉你的代码缺乏对文件内容的控制,所以在调用之前:

let myRecX = line.Split(',')

我建议定义一个私有方法,例如:

string SanitizeInputLine(string input) {
  // here do whatever is needed to bring back input to 
  // a valid format in a way that subsequent calls will not
  // fail

  return input;
}

应用它很简单;

let myRecX = SanitizeInputLine(line).Split(',')

作为一般规则,永远不要相信输入。

让我引用Howard/LeBlanc的编写安全代码的第 10 章,名为 _All Input Is Evil!__ :

...在数据得到验证之前,您永远不应该信任数据。不这样做会使您的应用程序易受攻击。或者,换一种说法:所有输入都是邪恶的,除非证明不是这样。

于 2013-03-22T18:45:22.140 回答