结构上的扩展方法

Ghy*_*hal 34 .net c# extension-methods struct

你能为结构添加扩展方法吗?

Pra*_*ana 27

是的,您可以在结构上添加扩展方法.根据扩展方法的定义,您可以轻松实现它.下面是int上的扩展方法示例

namespace ExtensionMethods
{
    public static class IntExtensions
     {
        public static bool IsGreaterEqualThan(this int i, int value)
        {
            return i >= value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但是要小心,因为结构被传递到扩展方法BY VALUE(因为结构要做).因此,您在扩展方法中对结构所做的任何修改都将丢失 - 除非您返回结构的结构(然后对传回的结构执行某些操作,例如将其重新分配给自身).没有办法在结构上执行扩展方法,并通过引用传递它(在C#中). (28认同)
  • BrainSlug83 C#7.2+现在支持结构扩展方法中的引用. (2认同)

sup*_*cat 19

可以向结构添加扩展方法,但有一个重要的警告.普通的struct方法接受this作为ref参数,但C#不允许定义这样做的扩展方法.虽然mutate的struct方法this有点危险(因为编译器允许在只读结构上调用struct方法,但是this按值传递),如果小心确保它们仅被使用,它们有时也会很有用.在适当的情况下.

顺便说一句,vb.net确实允许扩展方法this作为ByRef参数接受,无论它是类,结构还是未知类通用.在某些可能由结构实现接口的情况下,这可能会有所帮助.例如,如果一个人尝试调用一个类型List<string>.Enumerator的变量,该方法接受一个this类型的参数IEnumerator<string>,或者按值获取this一个通用约束的参数IEnumerator<string>,并且如果该方法试图推进枚举器,则任何进度都将被撤消当方法返回时.但是,通过引用采用约束泛型的扩展方法(可能在vb.net中)将按预期运行.


Pau*_*aul 6

对于未来的Google员工(和Bingers),这里有一些扩展结构的代码.此示例将值转换为double类型.

public static class ExtensionMethods {

   public static double ToDouble<T>(this T value) where T : struct {
      return Convert.ToDouble(value);
   }
}
Run Code Online (Sandbox Code Playgroud)

在此之后,您可以ToDouble()像使用一样使用ToString().注意溢出等转换项目.


Dav*_*ske 5

是的,您可以在结构/值类型上定义扩展方法。但是,它们与引用类型的扩展方法的行为不同。

例如,以下 C# 代码中的 GetA() 扩展方法接收结构的副本,而不是对结构的引用。这意味着结构上的 C# 扩展方法不能修改原始结构内容。

public static class TestStructExtensionMethods {
    public struct FooStruct {
        public int a;
    }
    public static int GetA(this FooStruct st) {
        return st.a;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了修改结构体内容,结构体参数需要声明为“ref”。但是,C# 中不允许使用“this ref”。我们能做的最好的是静态非扩展方法,例如:

// this works, but is inefficient, because it copies the whole FooStruct
// just to return a
public static int GetA(ref FooStruct st) {
    return st.a;
}
Run Code Online (Sandbox Code Playgroud)

在 VB.NET 中,您可以将其创建为 ByRef 结构扩展方法,因此它可以修改原始结构:

' This is efficient, because it is handed a reference to the struct
<Extension()> _ 
Public Sub GetA(ByRef [me] As FooStruct) As Integer
    Return [me].a
End Sub

' It is possible to change the struct fields, because we have a ref
<Extension()> _ 
Public Sub SetA(ByRef [me] As FooStruct, newval As Integer) 
    [me].a = newval
End Sub
Run Code Online (Sandbox Code Playgroud)