Reputation: 48402
I'm trying to write a Linq (to Objects) query that casts the results to an interface, as shown below:
var data = (from row in CicApplication.Vaporizer473Cache
where row.Coater == coater
select row).Cast<IVaporizerData>();
This appears to be the only way to do this, because I cannot create an instance of the interface in the select. I have two questions:
How is the cast actually done? Will it find each property in the source and copy its value to the interface property with the same name?
I have a property in my interface that isn't contained in the source, but I would like to somehow set its value during this operation. Is this possible? Or do I need to do it after the query, in a for each statement?
If it helps, the class definition for the source of the data (Vaporizer473Cache) looks as follows. The interface is very similiar.
internal class Vaporizer473
{
/// <summary>
/// Gets or sets the Coater property
/// </summary>
public string Coater { get; set; }
/// <summary>
/// Gets or sets the CoaterTime property
/// </summary>
public DateTime? CoaterTime { get; set; }
/// <summary>
/// Gets or sets the TemperatureLeftTubeA property
/// </summary>
public double? TemperatureLeftTubeA { get; set; }
/// <summary>
/// Gets or sets the TemperatureLeftTubeB property
/// </summary>
public double? TemperatureLeftTubeB { get; set; }
/// <summary>
/// Gets or sets the TemperatureRightTubeA property
/// </summary>
public double? TemperatureRightTubeA { get; set; }
/// <summary>
/// Gets or sets the TemperatureRightTubeB property
/// </summary>
public double? TemperatureRightTubeB { get; set; }
}
Upvotes: 5
Views: 7402
Reputation: 156469
Even though the compiler won't complain with the syntax you have provided, it won't run. You can't cast an object to an interface that it doesn't implement.
The Cast method is simply a convenience method that attempts to cast each object in the given IEnumerable
to the generic type you provide. If Vaporizer473 did implement IVaporizerData
, then you could just as easily say:
var data = from row in CicApplication.Vaporizer473Cache
where row.Coater == coater
select (IVaporizerData)row;
Secondly:
I have a property in my interface that isn't contained in the source, but I would like to somehow set its value during this operation. Is this possible? Or do I need to do it after the query, in a for each statement?
As you've figured out by now, your class will have to implement the property in your interface. (You can do this explicitly so it doesn't crowd intellisense on your actual class implementation and such.) It is possible to set values as you go by using a complex Select
delegate, but it's not what LINQ was made for, and I would highly discourage it. This is a case where a for
loop is the appropriate thing to do.
Bear in mind that if you modify items that come from your cache, you'll be modifying the original objects rather than clones of them. This can have far-reaching implications. You might want to create new objects to represent the data you're looking for instead.
Upvotes: 6
Reputation: 60498
To answer your first question, yes, this is how it is done. However, looking at your code, it seems that the Vaporizer473
class doesn't implement IVaporizorData
. Assuming that was just an oversight? If not, you'll need to implement that interface in order for the Cast<>()
call to work.
As for your second question, yes, you could set it in a for-each block afterwards, or you could use a Select
to both set the property and do the cast, like so:
CicApplication.Vaporizer473Cache
.Where( r => r.Coater = coater)
.Select((r) => {
r.SomeProperty = somevalue;
return r as IVaporizerData
});
Upvotes: 1
Reputation: 22945
Very simple. Casting an object to another type doesn't mean that another object is created. It is simple a different 'view' of the same object. Your class must implement the interface to be able to do that. So a cast means the same objects are still in the enumerable.
Since you don't create a new object when you cast an object, you cannot set the value of the extra property of the interface. But it also means that you already have the property in your object, since you object is implementing the interface.
Upvotes: 1