问题
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