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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/68750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:05:56  来源:igfitidea点击:

How do you write a C# Extension Method for a Generically Typed Class

提问by Matt Mitchell

This should hopefully be a simple one.

这应该是一个简单的。

I would like to add an extension method to the System.Web.Mvc.ViewPage< T > class.

我想向 System.Web.Mvc.ViewPage<T> 类添加一个扩展方法。

How should this extension method look?

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

My first intuitive thought is something like this:

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

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle(this ViewPage<Type> v)
        {
            return "";
        }
    }
}

Solution

解决方案

The general solution is this answer.

一般的解决方案是这个答案

The specific solution to extending the System.Web.Mvc.ViewPage class is my answerbelow, which started from the general solution.

扩展 System.Web.Mvc.ViewPage 类的具体解决方案是下面的回答,从通用解决方案开始。

The difference is in the specific case you need both a generically typed method declaration AND a statement to enforce the generic type as a reference type.

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

采纳答案by David Thibault

I don't have VS installed on my current machine, but I think the syntax would be:

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

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
        {
            return "";
        }
    }
}

回答by Corey Ross

It just needs the generic type specifier on the function:

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

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
        {
            return "";
        }
    }
}

Edit: Just missed it by seconds!

编辑:刚刚错过了几秒钟!

回答by Matt Mitchell

Thanks leddt. Doing that yielded the error:

谢谢ledt。这样做产生了错误:

The type 'TModel' must be a reference type in order to use it as parameter 'TModel' in the generic type or method

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

which pointed me to this page, which yielded this solution:

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

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> v) 
          where T : class
        {
            return "";
        }
    }
}

回答by Tim Jarvis

If you want the extension to only be available for the specified type you simply just need to specify the actual type you will be handling

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

something like...

就像是...

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

Note intellisense will then only display the extension method when you declare your (in this case) ViewPage with the matching type.

请注意,当您使用匹配类型声明(在本例中)ViewPage 时,intellisense 将仅显示扩展方法。

Also, best not to use the System.Web.Mvc namespace, I know its convenient to not have to include your namespace in the usings section, but its far more maintainable if you create your own extensions namespace for your extension functions.

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

回答by Eric Schoonover

Glenn Blockhas a good example of implementing a ForEachextension method to IEnumerable<T>.

Glenn Block有一个很好的例子来实现ForEach扩展方法到IEnumerable<T>.

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

回答by chadmyers

namespace System.Web.Mvc
{
    public static class ViewPageExtensions
    {
        public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
            where T : class
        {
            return "";
        }
    }
}

You may also need/wish to add the "new()" qualifier to the generic type (i.e. "where T : class, new()" to enforce that T is both a reference type (class) and has a parameterless constructor.

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

回答by Tod Thomson

Here's an example for Razor views:

以下是 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();
    }
}

You really don't need to use the Generic version as the generic one extends the non-generic one so just put it in the non-generic base class and you're done :)

你真的不需要使用通用版本,因为通用版本扩展了非通用版本,所以只需将它放在非通用基类中就可以了:)