简体   繁体   English

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

[英]Why doesn't c# support an object with an interface as a parameter?

I have the following class declaration: 我有以下类声明:

public class EntityTag : BaseEntity, ITaggable

I have an Html helper method: 我有一个Html帮助方法:

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

This is my ASP.NET MVC ascx: 这是我的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") %>

When I pass in an IQueryable collection to the ascx, I get this error: 当我将IQueryable集合传递给ascx时,我收到此错误:

Compiler Error Message: CS1928: 'System.Web.Mvc.HtmlHelper>' does not contain a definition for 'TagCloud' and the best extension method overload 'EDN.MVC.Helpers.EdnHelpers.TagCloud(System.Web.Mvc.HtmlHelper, System.Linq.IQueryable, int, string)' has some invalid arguments 编译器错误消息:CS1928:'System.Web.Mvc.HtmlHelper>'不包含'TagCloud'的定义和最佳扩展方法重载'EDN.MVC.Helpers.EdnHelpers.TagCloud(System.Web.Mvc.HtmlHelper, System.Linq.IQueryable,int,string)'有一些无效的参数

If I try to explicitly convert the object collection with this: 如果我尝试使用以下方法显式转换对象集合:

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

I get the same error - the values I'm passing in are not liked by the compiler. 我得到了同样的错误 - 编译器不喜欢我传入的值。

Shouldn't my EntityTag class automatically be supported as IQueryable? 我的EntityTag类不应该自动支持IQueryable吗? What am I missing? 我错过了什么? It's got to be something obvious. 它必须是明显的东西。 (I hope.) (我希望。)

Essentially, you're trying to pass an object of the non-generic type IQueryable to a method that accepts the generic IQueryable<ITaggable> , which the compiler cannot "match", resulting in the CS1928 (since the two types are, in fact, different). 本质上,您试图将非泛型类型IQueryable的对象传递给接受通用IQueryable<ITaggable> ,编译器无法“匹配”,从而产生CS1928(因为这两种类型实际上是,不同)。

In your overload that accepts an IQueryable<object> (which is already doing the necessary conversion to a generic list), you simply need to call the generic version of AsQueryable instead of the non-generic one, as such: 在你的重载中接受一个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);  
}  

Allow me to add, as well, that IQueryable<T> derives from IQueryable , meaning that not all IQueryable objects are IQueryable<T> , thus making the conversion necessary. 另外,请允许我添加IQueryable<T>派生自IQueryable ,这意味着并非所有IQueryable对象都是IQueryable<T> ,因此必须进行转换。 If the situation were reversed, ie your "real" helper method was defined to handle IQueryable objects, then you certainly would have no problem passing an IQueryable<T> to that method (since all IQueryable<T> objects are, in fact, IQueryable ). 如果情况发生逆转,即你的“真正的”辅助方法被定义为处理IQueryable对象,那么将IQueryable<T>传递给该方法肯定没有问题(因为所有IQueryable<T>对象实际上都是IQueryable )。

Per Craig Stuntz, a much more elegant solution using LINQ features: <%= Html.TagCloud(Model.Select(t => (ITaggable)t), 6, "entity-tags") %> . Per Craig Stuntz,一个使用LINQ功能的更优雅的解决方案: <%= Html.TagCloud(Model.Select(t => (ITaggable)t), 6, "entity-tags") %> You can also use <%= Html.TagCloud(Model.Cast<ITaggable>(), 6, "entity-tags") %> if your queryable provider supports it. 如果您的可查询提供程序支持,您还可以使用<%= Html.TagCloud(Model.Cast<ITaggable>(), 6, "entity-tags") %>

C# 4.0 will support it. C#4.0将支持它。 Search for "Covariance and Contravariance in C# 4" 搜索“C#4中的协方差和逆变”

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM