无法在扩展方法中使用ref和out作为第一个(“this”)参数?

时间:2010-04-11 20:31:11

标签: c# .net extension-methods

为什么禁止使用Extension Method修饰符调用ref

这是可能的:

public static void Change(ref TestClass testClass, TestClass testClass2)
{
    testClass = testClass2;
}

这不是:

public static void ChangeWithExtensionMethod(this ref TestClass testClass, TestClass testClass2)
{
    testClass = testClass2;
}

但为什么?

6 个答案:

答案 0 :(得分:21)

您必须明确指定refout。您将如何使用扩展方法执行此操作?此外,你真的想要吗?

TestClass x = new TestClass();
(ref x).ChangeWithExtensionMethod(otherTestClass);
// And now x has changed?

或者您是否希望不必指定ref部分,仅用于扩展方法中的第一个参数?

对我来说,这听起来很奇怪,说实话,还有一个不可读(或至少难以预测)代码的秘诀。

答案 1 :(得分:8)

我同意Jon Skeet等人的回答。关于如何允许“ref this”扩展方法可以使代码更加模糊。但是,如果您查看.Net Framework中的某些命名空间,则在结构上调用的方法通常会对其进行更改。

以System.Drawing结构(Point,Rectangle等)为例。其中每一个都有改变结构本身的方法(例如Offset,Inflate等)。我不是说这是一个好主意,事实上我个人觉得Offset,Inflate等变异结构本身而不是返回新结构非常烦人,我知道你们中的一些人反对改变结构的想法一般

我怀疑在任何情况下调用引用类型的方法都会改变引用(除非是String类,我可以想象可能会有一些编译器魔术来切换引用以执行实习,等等)。因此,防止“this ref”与引用类型一起使用是有意义的,因为更改引用将是调用方法的完全非标准的副作用。

但是对于结构体,允许“this ref”不会显着降低代码可读性,而不仅仅是Rectangle.Inflate等,它将提供用扩展函数“模拟”这种行为的唯一方法。 / p>

正如旁注,这里有一个例子,其中“this ref”可能有用,恕我直言仍然可读:

void SwapWith<T>(this ref T x, ref T y) {
   T tmp = x; x = y; y = tmp;
}

答案 2 :(得分:3)

我同意它对struct

很有用

所以我想建议为struct创建扩展方法。此关键字应始终通过引用传递struct

无论如何,

类始终通过引用传递。每当我们创建扩展方法时,我们希望它表现得像一个真正的方法。所以类和结构的真正方法可以修改它的值。扩展方法应该也可以

答案 3 :(得分:2)

我知道这是一个古老的问题。但是情况已经变了。万一有人在找这个。

从C#7.2开始,您可以将ref修饰符添加到第一个 扩展方法的参数。添加ref修饰符意味着 第一个参数通过引用传递。这使您可以编写 扩展方法,用于更改要扩展的结构的状态。

来源:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods#:~:text=Beginning%20with%20C%23%207.2%2C%20you,of%20the%20struct%20being%20extended

public struct MyProperties
{
    public string MyValue { get; set; }
}

public static class MyExtensions
{
    public static void ChangeMyValue(this ref MyProperties myProperties)
    {
        myProperties.MyValue = "hello from MyExtensions";
    }
}

public class MyClass
{
    public MyClass()
    {
        MyProperties myProperties = new MyProperties();
        myProperties.MyValue = "hello world";
        myProperties.ChangeMyValue();
    }
}

答案 4 :(得分:1)

这意味着调用myObject.ChangeWithExtentionMethod(otherObject)实际上有可能改变myObject的值。 IMO,当你可以通过使用带有ref的常规非扩展方法来实现期望的效果时,这不会产生非常易读的代码。

编辑:我的观点是,方法调用应该要求您在通过引用传递内容时使用ref关键字。使用带有扩展方法的参数'this'参数会违反该行为。

答案 5 :(得分:1)

在C#7.2中,您可以使用引用扩展方法

相关问题