Impossible to use ref and out for first (“this”) p

2020-01-24 02:47发布

问题:

Why is it forbidden to call Extension Method with ref modifier?

This one is possible:

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

And this one not:

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

But why?

回答1:

You have to specify ref and out explicitly. How would you do this with an extension method? Moreover, would you really want to?

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

Or would you want to not have to specify the ref part, just for the first parameter in extension methods?

It just sounds weird to me, to be honest, and a recipe for unreadable (or at least hard-to-predict) code.



回答2:

I agree with the answers from Jon Skeet et al. about how allowing "ref this" extension methods could make the code more obscure. But if you look at some namespaces in the .Net Framework, it is common for a method invoked on a struct to alter it.

Take for example the System.Drawing structs (Point, Rectangle, etc). Each of these has methods (e.g. Offset, Inflate, etc) that mutate the struct itself. I'm not saying this is a good idea, in fact I personally find it very annoying that Offset, Inflate, etc mutate the structs themselves instead of returning new ones, and I know some of you are opposed to the idea of mutable structs in general.

I doubt there are any cases where invoking a method of a reference type will change the reference (unless it's with the String class, where I can imagine there might be some compiler magic to switch references to perform interning, etc). So it makes sense to prevent "this ref" from being used with reference types, because changing a reference would be a completely non-standard side-effect of calling a method.

But in regards to structs, allowing "this ref" would not significantly decrease code readability any more than Rectangle.Inflate, etc, and it would provide the only means to "simulate" that kind of behavior with an extension function.

Just as a side-note, here is one example where "this ref" might be useful, and IMHO still readable:

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


回答3:

In C# 7.2 you can use ref extension methods



回答4:

I agree that it useful for struct

So I want to propose that for making extension method for struct. this keyword should always pass struct by reference

class always pass by reference anyway. And whenever we create extension method we want it to behave like a real method. So real method of class and struct can modified its value. Extension method should be able to too



回答5:

This would mean that calling myObject.ChangeWithExtentionMethod(otherObject) would actually have the potential to change myObject's value. IMO, that wouldn't make for very readable code when you can instead achieve the desired effect by using a regular non-extension method with a ref.

EDIT: My point is, the method call should require you to use the ref keyword any time that you're passing something by reference. Using ref with an extension method's 'this' parameter would violate that behavior.