Reputation: 5384
I've been staring at this for awhile and not sure how to fix it.
All I'm trying to do is fill in the arptable description property where it matches the address in the device table. I am not trying to create another collection from the arptable.
Error:
The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Here is the offending code:
IEnumerable<ARPTABLE> GetARPTable()
{
IpTable arp = new IpTable();
IEnumerable<ARPTABLE> arptable = arp.GetArpTable();
arptable.ToList().ForEach(i =>
{
DeviceTable.Where(j => j.PhysicalAddress == i.MAC)
.Select(y =>
{
i.Description = y.Model ?? y.DeviceName;
});
});
return arptable;
}
where DeviceTable is
public ObservableCollection<Device> DeviceTable { get; set; }
Thanks for any help (or a better way).
Upvotes: 2
Views: 808
Reputation: 12616
LINQ is not ment to be used for filling in data. It's a query language and so the Select
method returns a new sequence. Just do it with foreach. I would image it could look like this, although I'm not exactly sure if I got the logic right.
foreach(var table in arptable)
{
var device = DeviceTable.SingleOrDefault(...);
if (device != null)
{
table.Description = device.Model ?? device.DeviceName;
}
}
As for your current form
arptable.ToList().ForEach(i =>
this is really not necessary, why cast the sequence to list if you don't have to? Just to use that ForEach
? We can do better.
DeviceTable.Where(j => j.PhysicalAddress == i.MAC)
.Select(y => i.Description = y.Model ?? y.DeviceName);
This returns a new sequence, which you are not storing in any local variable. LINQ queries should not have side effect, it's against the lambda calculus, the idea behind LINQ itself.
Upvotes: 2
Reputation: 34207
i like the other answers. if you still want to use linq
, this is how you would:
IEnumerable<ARPTABLE> GetARPTable()
{
IpTable arp = new IpTable();
IEnumerable<ARPTABLE> arptable = arp.GetArpTable();
arptable = arptable.Select(i =>
{
Device device = DeviceTable.SingleOrDefault(j => j.PhysicalAddress == i.MAC);
if (device != null)
{
i.Description = device.Model ?? device.DeviceName;
}
return i;
});
return arptable;
}
Upvotes: 1
Reputation: 70671
The compiler is having trouble because your lambda expression isn't written correctly and so it fails on type inference. Unfortunately, the whole construction of the method is broken and I'm not sure I really understand what you're trying to accomplish here.
But in terms of getting it to compile, your method should look more like this:
IEnumerable<ARPTABLE> GetARPTable()
{
IpTable arp = new IpTable();
IEnumerable<ARPTABLE> arptable = arp.GetArpTable();
foreach (var i in arptable)
{
Device j = DeviceTable.FirstOrDefault(j => j.PhysicalAddress == i.MAC);
if (j != null)
{
i.Description = j.Model ?? j.DeviceName;
}
}
return arptable;
}
As a general note: do not use methods like Select()
as a way to simply visit each element in the collection. The expression you give to the Select()
method will not actually be evaluated unless you evaluate the IEnumerable<T>
that was returned, which you did not in this case. And even if you do evaluate the IEnumerable<T>
, it's an inefficient misuse of the method.
Also, while List<T>.ForEach()
could be considered convenient by some, it is wasteful to convert an IEnumerable<T>
to a List<T>
just for the purpose of calling that method. A regular foreach statement works fine and is more efficient.
Upvotes: 3