如何为泛型类编写 C# 扩展方法

Posted

技术标签:

【中文标题】如何为泛型类编写 C# 扩展方法【英文标题】:How do you write a C# Extension Method for a Generically Typed Class 【发布时间】:2010-09-09 06:50:33 【问题描述】:

希望这应该是一个简单的。

我想在 System.Web.Mvc.ViewPage 类中添加一个扩展方法。

这个扩展方法应该怎么看?

我的第一个直觉想法是这样的:

namespace System.Web.Mvc

    public static class ViewPageExtensions
    
        public static string GetDefaultPageTitle(this ViewPage<Type> v)
        
            return "";
        
    

解决方案

一般的解决方案是this answer。

扩展System.Web.Mvc.ViewPage类的具体方案是下面的my answer,从general solution开始。

不同之处在于,在特定情况下,您需要一个泛型类型的方法声明和一个将泛型类型强制为引用类型的语句。

【问题讨论】:

【参考方案1】:

我当前的机器上没有安装 VS,但我认为语法是:

namespace System.Web.Mvc

    public static class ViewPageExtensions
    
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
        
            return "";
        
    

【讨论】:

见***.com/questions/68750/…【参考方案2】:

谢谢leddt。 这样做会产生错误:

类型“TModel”必须是引用 键入以将其用作参数 泛型类型或方法中的“TModel”

这将我指向this page,它产生了这个解决方案:

namespace System.Web.Mvc

    public static class ViewPageExtensions
    
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v) 
          where T : class
        
            return "";
        
    

【讨论】:

【参考方案3】:

它只需要函数上的泛型类型说明符:

namespace System.Web.Mvc

    public static class ViewPageExtensions
    
        public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
        
            return "";
        
    

编辑:只是错过了几秒钟!

【讨论】:

【参考方案4】:
namespace System.Web.Mvc

    public static class ViewPageExtensions
    
        public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
            where T : class
        
            return "";
        
    

您可能还需要/希望将“new()”限定符添加到泛型类型(即“where T : class, new()”以强制 T 既是引用类型(类)又具有无参数构造函数。

【讨论】:

【参考方案5】:

Glenn Block 有一个很好的例子来实现ForEach 扩展方法到IEnumerable&lt;T&gt;

来自他的blog post:

public static class IEnumerableUtils

    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    
        foreach(T item in collection)
            action(item);
    

【讨论】:

【参考方案6】:

如果您希望扩展仅适用于指定类型 你只需要指定你将要处理的实际类型

类似...

public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)

  ...

注意,智能感知将仅在您声明(在本例中)具有匹配类型的 ViewPage 时显示扩展方法。

另外,最好不要使用 System.Web.Mvc 命名空间,我知道不必在 usings 部分包含命名空间会很方便,但如果您为扩展功能创建自己的扩展命名空间,它更易于维护。

【讨论】:

【参考方案7】:

这是 Razor 视图的示例:

public static class WebViewPageExtensions

    public static string GetFormActionUrl(this WebViewPage view)
    
        return string.Format("/0/1/2", view.GetController(), view.GetAction(), view.GetId());
    

    public static string GetController(this WebViewPage view)
    
        return Get(view, "controller");
    

    public static string GetAction(this WebViewPage view)
    
        return Get(view, "action");
    

    public static string GetId(this WebViewPage view)
    
        return Get(view, "id");
    

    private static string Get(WebViewPage view, string key)
    
        return view.ViewContext.Controller.ValueProvider.GetValue(key).RawValue.ToString();
    

您确实不需要使用通用版本,因为通用版本扩展了非通用版本,因此只需将其放入非通用基类中即可:)

【讨论】:

以上是关于如何为泛型类编写 C# 扩展方法的主要内容,如果未能解决你的问题,请参考以下文章

如何在 typescript 中为泛型类编写扩展作为 getter

c# 在不知道类型的情况下,如何判断并使用带泛型的扩展方法?

其参数扩展嵌套类的泛型类

如何在 Typescript 中正确扩展泛型类?

泛型和枚举

Java泛型