为什么禁止使用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;
}
但为什么?
答案 0 :(得分:21)
您必须明确指定ref
和out
。您将如何使用扩展方法执行此操作?此外,你真的想要吗?
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修饰符意味着 第一个参数通过引用传递。这使您可以编写 扩展方法,用于更改要扩展的结构的状态。
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中,您可以使用引用扩展方法