Handling null in Linq

守給你的承諾、 提交于 2019-12-11 03:09:16

问题


I am new to linq, and this keeps popping on a null volume field. The file is unpredictable, and it will happen so I would like to put a 0 in where there is an exception. any quick and easy way to do it?

     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 =", ""))

            };

回答1:


If you would like to use a default when the incoming data is null, empty, or consists entirely of whitespace characters, you can do it like this:

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

However, this is a "quick and dirty" way of achieving what you need, because the position of each named parameter remains hardcoded. A more robust way would be writing a mini-parser that pays attention to the names of attributes specified in the file, rather than replacing them with an empty string.




回答2:


You could use something like this, which offers an expressive way to write what you want:

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

Used like:

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

The function indirection and implicit array construction may incur a slight performance penalty, but it gives you a nice syntax with which to specify a number of possible conversions, where the first successful one is taken.




回答3:


I think here there's an issue beyond the use of Linq.

In general is bad practice manipulating file data before sanitizing it.

Ever if the following question is on the filename (rather than it's content) is a good starting point to understand the concept of sanitizing input:

C# Sanitize File Name

After all yourself tells that your code lacks control of the file content, so before call:

let myRecX = line.Split(',')

I suggest define a private method like:

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

Applying it is straightforward;

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

As general rule never trust input.

Let me quote Chapter 10 named _All Input Is Evil!__ of Writing Secure Code by Howard/LeBlanc:

...you should never trust data until data is validated. Failure to do so will render your application vulnerable. Or, put another way: all input is evil until proven otherwise.



来源:https://stackoverflow.com/questions/15577213/handling-null-in-linq

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!