为什么c#不支持将接口作为参数的对象?

时间:2010-01-08 01:20:17

标签: c# .net asp.net-mvc

我有以下类声明:

public class EntityTag : BaseEntity, ITaggable

我有一个Html帮助方法:

public static string TagCloud(this HtmlHelper html, IQueryable<ITaggable> taggables, 
  int numberOfStyleVariations, string divId)

这是我的ASP.NET MVC ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IQueryable<EDN.MVC.Models.EntityTag>>" %>
<%@Import Namespace="EDN.MVC.Helpers" %>
<%= Html.TagCloud(Model, 6, "entity-tags") %>

当我将IQueryable集合传递给ascx时,我收到此错误:

编译器错误消息:CS1928:'System.Web.Mvc.HtmlHelper&gt;'不包含'TagCloud'的定义和最佳扩展方法重载'EDN.MVC.Helpers.EdnHelpers.TagCloud(System.Web.Mvc.HtmlHelper,System.Linq.IQueryable,int,string)'有一些无效的参数< / p>

如果我尝试使用以下方法显式转换对象集合:

    public static string TagCloud(this HtmlHelper html, IQueryable<Object> taggables, int numberOfStyleVariations, string divId)
    {
        var tags = new List<ITaggable>();
        foreach (var obj in taggables)
        {
            tags.Add(obj as ITaggable);
        }
        return TagCloud(html, tags.AsQueryable(), numberOfStyleVariations, divId);
    }

我得到了同样的错误 - 编译器不喜欢我传入的值。

我的EntityTag类不应该自动支持IQueryable吗?我错过了什么?它必须是明显的东西。 (我希望。)

3 个答案:

答案 0 :(得分:5)

基本上,您尝试将非泛型类型IQueryable的对象传递给接受通用IQueryable<ITaggable>的方法,编译器无法“匹配”该方法,从而产生CS1928(因为这两种类型实际上是不同的。)

在您的重载中接受IQueryable<object>(已经进行必要的转换到通用列表),您只需要调用AsQueryable的通用版本而不是非泛型版本,就这样:

public static string TagCloud(this HtmlHelper html, IQueryable taggables, int numberOfStyleVariations, string divId)  
{  
    var tags = new List<ITaggable>();  
    foreach (var obj in taggables)  
    {  
        tags.Add(obj as ITaggable);  
    }  
    return TagCloud(html, tags.AsQueryable<ITaggable>(), numberOfStyleVariations, divId);  
}  

同样请允许我添加IQueryable<T>来自IQueryable,意味着并非所有IQueryable个对象都是IQueryable<T>,因此必须进行转换。如果情况发生逆转,即你的“真正的”辅助方法被定义为处理IQueryable个对象,那么你可以毫无疑问地将IQueryable<T>传递给该方法(因为所有IQueryable<T>个对象都是如此实际上是IQueryable)。

Per Craig Stuntz,使用LINQ功能的更优雅的解决方案: <%= Html.TagCloud(Model.Select(t => (ITaggable)t), 6, "entity-tags") %>。如果您的可查询提供程序支持,也可以使用<%= Html.TagCloud(Model.Cast<ITaggable>(), 6, "entity-tags") %>

答案 1 :(得分:2)

C#4.0将支持它。 搜索“C#4中的协方差和逆变”

答案 2 :(得分:1)

您的EntityTag类是IQueryable,但是编译器不知道您的标记列表实际上是EntityTag个对象的列表,它只知道它是一个对象列表实施ITaggable,可能不是IQueryable

相关问题