4

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; }

}

4

3 回答 3

5

即使编译器不会抱怨您提供的语法,它也不会运行。您不能将对象强制转换为它未实现的接口。

Cast 方法只是一种方便的方法,它尝试将给定IEnumerable中的每个对象转换为您提供的泛型类型。如果 Vaporizer473确实实现了IVaporizerData,那么您可以很容易地说:

var data = from row in CicApplication.Vaporizer473Cache
           where row.Coater == coater
           select (IVaporizerData)row;

第二:

我的界面中有一个不包含在源代码中的属性,但我想在此操作期间以某种方式设置它的值。这可能吗?还是我需要在查询之后,在每个语句中执行它?

正如您现在所知道的,您的类将必须在您的接口中实现该属性。(您可以明确地执行此操作,这样它就不会在您的实际类实现等上挤满智能感知。)可以通过使用复杂的Select委托来设置值,但这不是 LINQ 的用途,我会高度劝阻它。在这种情况下,for循环是合适的做法。

请记住,如果您修改来自缓存的项目,您将修改原始对象而不是它们的克隆。这可能会产生深远的影响。您可能希望创建新对象来表示您正在寻找的数据。

于 2012-12-11T19:32:32.117 回答
1
  1. 非常简单。一个对象转换为另一种类型并不意味着创建了另一个对象。对同一对象的不同“视图”很简单。你的类必须实现接口才能做到这一点。所以演员表意味着相同的对象仍然在可枚举中。

  2. 由于在转换对象时不会创建新对象,因此无法设置接口的额外属性的值。但这也意味着您已经在对象中拥有该属性,因为您的对象正在实现接口。

于 2012-12-11T19:35:07.213 回答
1

要回答您的第一个问题,是的,这就是它的完成方式。但是,查看您的代码,Vaporizer473该类似乎没有实现IVaporizorData. 假设这只是一个疏忽?如果没有,您需要实现该接口才能使Cast<>()调用正常工作。

至于你的第二个问题,是的,你可以在之后将它设置在一个 for-each 块中,或者你可以使用 aSelect来设置属性并进行强制转换,如下所示:

CicApplication.Vaporizer473Cache
.Where( r => r.Coater = coater)
.Select((r) => {
   r.SomeProperty = somevalue;
   return r as IVaporizerData
});
于 2012-12-11T19:35:25.343 回答