【问题标题】:Generic constraints with C# Expression<TDelegate> - Cannot implicitly convert Type使用 C# Expression<TDelegate> 的通用约束 - 无法隐式转换类型
【发布时间】:2012-07-12 12:52:53
【问题描述】:

我已经开始使用 C# 表达式构造,我有一个关于泛型如何在以下情况下应用的问题:

假设我有一个类型MyObject,它是许多不同类型的基类。在这个类中,我有以下代码:

// This is a String Indexer Expression, used to define the string indexer when the object is in a collection of MyObjects
public Expression<Func<MyObject, string, bool>> StringIndexExpression { get; private set;}


// I use this method in Set StringIndexExpression and T is a subtype of MyObject
protected void DefineStringIndexer<T>(Expression<T, string, bool>> expresson) where T : MyObject
{
    StringIndexExpression = expression;
}

这就是我使用DefineStringIndexer的方式:

public class MyBusinessObject : MyObject
{

   public string Name { get; set; }

   public MyBusinessObject() 
   {
       Name = "Test";
       DefineStringIndexer<MyBusinessObject>((item, value) => item.Name == value);
   }

}

但是在DefineStringIndexer 里面的赋值中我得到了编译错误:

不能隐式转换类型 System.Linq.Expression.Expression to System.Linq.Expression.Expression >

在这种情况下,我可以将泛型与 C# 表达式一起使用吗?我想在 DefineStringIndexer 中使用 T,这样我就可以避免在 lambda 中强制转换 MyObject。

【问题讨论】:

  • 您的代码将无法工作,因为 .NET 不支持可变类型之间的协变。您可以使用不可变类型(但这可能对您不起作用!)。你可以试试DefineStringIndexer&lt;MyObject&gt;((item , value) =&gt; ((MyBusinessObject)item).Name == value);.. 这可能有用!
  • 或者,您也可以将MyObject 设为泛型并使用MyBusinessObject : MyObject&lt;MyBusinessObject&gt;,然后为T 类型的Expression 创建类型参数

标签: c# generics lambda expression


【解决方案1】:

分配将不起作用,因为Func&lt;MyBusinessObject,string,bool&gt; 类型与Func&lt;MyObject,string,bool&gt; 的分配不兼容。不过这两个 functor 的参数是兼容的,所以可以添加一个 wrapper 让它工作:

protected void DefineStringIndexer<T>(Func<T,string,bool> expresson) where T : MyObject {
    StringIndexExpression = (t,s) => expression(t, s);
}

【讨论】:

  • 好提示 :) 没想到!
【解决方案2】:

这对你更有效吗?

编辑:将 &lt;T&gt; 添加到约束 - 认为您将需要它:)

class MyObject<T>
{
    // This is a String Indexer Expression, used to define the string indexer when the object is in a collection of MyObjects 
    public Expression<Func<T, string, bool>> StringIndexExpression { get; private set;} 


    // I use this method in Set StringIndexExpression and T is a subtype of MyObject 
    protected void DefineStringIndexer<T>(Expression<T, string, bool>> expresson) 
        where T : MyObject<T> // Think you need this constraint to also have the generic param
    { 
        StringIndexExpression = expression; 
    } 
}

然后:

public class MyBusinessObject : MyObject<MyBusinessObject>
{ 

   public string Name { get; set; } 

   public MyBusinessObject()  
   { 
       Name = "Test"; 
       DefineStringIndexer<MyBusinessObject>((item, value) => item.Name == value); 
   } 

} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    相关资源
    最近更新 更多