Randy Minder
Randy Minder

Reputation: 48402

Casting Linq Query Results to an Interface

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:

  1. 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?

  2. 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

Answers (3)

StriplingWarrior
StriplingWarrior

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

Eric Petroelje
Eric Petroelje

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

Maarten
Maarten

Reputation: 22945

  1. 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.

  2. 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

Related Questions