I'm attempting to write a simple Select
method on a class that inherits from IList
.
public class RowDataCollection : IList<RowData> {
private List<RowData> rowList;
internal RowDataCollection(List<RowData> data) {
rowList = data;
}
// ...
}
public RowDataCollection Rows;
public RowDataCollection Select(string colName, object value) {
List<RowData> rowList = from item in Rows
where item[colName].Value == value
select item;
return new RowDataCollection(rowList);
}
Some problems I'm having:
First:
Cannot implicitly convert type 'IEnumerable<RowData>' to 'List<RowData>'. An explicit conversion exists (are you missing a cast?)
OK, where does the CAST go?
Second:
colName
value (i.e. String.IsNullOrEmpty(colName)
) or a null parameter (object value == null)
.How would I handle the way my function returns if the input parameters are invalid?
[Solved]
I edited my Select
statement (even renamed it per the suggestions here). I had to use a switch to cast to the data type that the data was in, but it does work.
public RowDataCollection SelectRow(string colName, object value) {
if (!String.IsNullOrEmpty(colName) && (value != null) && (0 < Rows.Count)) {
switch (Rows[0][colName].GetValueType()) {
case TableDataType.Boolean:
return new RowDataCollection(Rows.Where(r => (bool)r[colName].Value == (bool)value).ToList());
case TableDataType.Character:
return new RowDataCollection(Rows.Where(r => (char)r[colName].Value == (char)value).ToList());
case TableDataType.DateTime:
return new RowDataCollection(Rows.Where(r => (DateTime)r[colName].Value == (DateTime)value).ToList());
case TableDataType.Decimal:
return new RowDataCollection(Rows.Where(r => (Decimal)r[colName].Value == (Decimal)value).ToList());
case TableDataType.Integer:
return new RowDataCollection(Rows.Where(r => (int)r[colName].Value == (int)value).ToList());
case TableDataType.String:
return new RowDataCollection(Rows.Where(r => r[colName].Value.ToString() == value.ToString()).ToList());
}
}
return null;
}
[Solved (short version)]
Jon Skeet posted this about the same time I posted my solution, and (as always) his code is much nicer.
public RowDataCollection SelectRow(string colName, object value) {
List<RowData> rowList = Rows.Where(r => r[colName].Value.Equals(value)).ToList();
return new RowDataCollection(rowList);
}
@Jon Skeet: If I ever see your face in the same line at some software developer position I'm applying for, I'm just going to turn around and go home.
@Everyone: Thanks for all the help!
The result of a query like that isn't a List<T>
, it's an IEnumerable<T>
. If you want to convert that into a List<T>
, just call ToList
:
List<RowData> rowList = (from item in Rows
where item[colName].Value == value
select item).ToList();
As it happens, you're only calling Where
in your query. I would rewrite this as:
List<RowData> rowList = Rows.Where(item => item[colName].Value.Equals(value))
.ToList();
I'd also rename the method to something which is obviously filtering rather than projecting, given that the latter is the more common use of the term "select" in LINQ.
As for input parameters - I suggest you validate the arguments and throw an exception if they're not valid:
if (string.IsNullOrEmpty(colName))
{
throw new ArgumentException("colName");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With