Add dereference operator/keyword to complement the existing "ref" keyword. #1553
Replies: 15 comments
-
@Korporal IIRC the team wanted the |
Beta Was this translation helpful? Give feedback.
-
@HaloFour - OK that's a reasonable motive I guess, one could get into a mess if they weren't careful. However the code is verifiable (that is it is not unsafe) and I wonder why this particular scenario is treated as a special case? A programmer must understand what they write. I can write
where the method returns a pointer and it does behave as we expect (I get a local copy of the returned pointer not some automatically dereferenced value), this isn't treated as special like "ref" is. |
Beta Was this translation helpful? Give feedback.
-
First of all, what you're proposing would be a breaking change, so I think there's pretty much zero chance that this would be accepted. Second, I think the changes made in C# 7.x make sense, because they're consistent with how void MyMethod(ref Whatever arg)
{
var datum = arg;
} Here, |
Beta Was this translation helpful? Give feedback.
-
@svick - Well I don't expect any major change to support what I'm asking, but it is unwieldy having to write this:
for a method that itself returns a |
Beta Was this translation helpful? Give feedback.
-
So what kind of change that isn't a breaking change do you expect? |
Beta Was this translation helpful? Give feedback.
-
I agree that having to write If anything, I would like to see the ability to do: I think the former (just requiring |
Beta Was this translation helpful? Give feedback.
-
@tannergooding - Ineteresting:
I actually began by coding
only to end up spending time digging into how to actually code it. That syntax above seemed entirely natural to me and I fully expected it compile and run. I remember thinking to myself as I coded this:
"...that's never gonna compile, I'm clutching at straws now..." |
Beta Was this translation helpful? Give feedback.
-
Tanner's suggestion (if that's what it is) seems absolutely fine. |
Beta Was this translation helpful? Give feedback.
-
I agree that the purpose was to call attention to it. I believe the syntax is consistent with the way out parameters work so I don't agree that anything needs to be changed. Foo(out var someValue); |
Beta Was this translation helpful? Give feedback.
-
@CoolDadTx @svick @tannergooding @HaloFour I want to discuss this some more if I may. There is a subtle problem here that can lead to serious misbehavior at runtime. If the following compiles:
then so does the following:
Yet these are not doing the same thing. It is only because I'm debugging and using the Memory windows under debug and I'm intimately familiar with manipulating raw memory and so on, that I discovered this. As I mentioned in the OP I initially coded this and it compiled and ran:
because
But it wasn't and I only discovered this because I'm debugging and examining memory and so on, I spotted that something was wrong because I'm very aware of what's going on with my code (by which I mean in this case Any developer that simply consumed This is not good, the thing being returned (a CLR reference) is the same in each case yet by declaring the variable datum with or without a This really doesn't make sense to me and I don't know why anyone would intentionally design this. If a method returns a Note that when the method returns a These recent changes to C# are very very helpful and enable me to rewrite a lot of low level code that was previously written in C and accessed via interop. But as use of these features begins to proliferate then cases of someone forgetting about the There are other bizarre variations here too:
compiles even though MyMethod is returning a
despite the fact that MyMethod is returning a A dereference keyword perhaps like 'val' might have helped hugely here:
Because C# makes references explicit via |
Beta Was this translation helpful? Give feedback.
-
@Korporal, it may help if you consider that That is, even in standard C++, when using references, you have to explicitly indicate that you want a reference returning function to not implicitly dereference a given value. The same logic applies to C# here (with the caveat the C# gives an error if you do C++ Example Code, displaying reference semanticsstruct Int128
{
uint64_t lower;
int64_t upper;
};
Int128 MaxValue = { UINT64_MAX, INT64_MAX };
Int128& get_MaxValueRef()
{
return MaxValue;
}
Int128* get_MaxValuePtr()
{
return &MaxValue;
}
int main()
{
Int128 maxValue = get_MaxValueRef();
Int128& maxValueRef = get_MaxValueRef();
Int128* maxValuePtr = get_MaxValuePtr();
maxValue.upper = 0;
// maxValue.upper = 0
// maxValueRef.upper = UINT64_MAX
// maxValuePtr.upper = UINT64_MAX
maxValueRef.upper = 1;
// maxValue.upper = 0
// maxValueRef.upper = 1
// maxValuePtr.upper = 1
maxValuePtr->upper = 2;
// maxValue.upper = 0
// maxValueRef.upper = 2
// maxValuePtr.upper = 2
return 0;
} |
Beta Was this translation helpful? Give feedback.
-
@tannergooding - What you say is true of course but C# is not C++ so there's no reason to use that language as the motivator for how to continue enhancing C#. Bear in mind most C# developers have probably never seen or used C or C++. Explicit referencing with implicit dereferencing is not symmetrical and I think the "double ref" one needs in some of the examples above are evidence enough that this is somewhat messy now in C#. The way
results in Of course you can say that |
Beta Was this translation helpful? Give feedback.
-
Most C# developers also don't use
Just seeing that could would make me assume that it isn't returning a In any case, the way |
Beta Was this translation helpful? Give feedback.
-
Except that the latest changes to C# in this area increase the utility of the
Why would you assume it isn't returning a Surely of all the assumptions one could make about that statement the assumption that
Leads to datum having a type that matches the methods result type, is the most rational assumption, I'd be truly surprised if the majority of C# developers assumed otherwise.
Which is not true, I did suggest this for example: A dereference keyword perhaps like 'val' might have helped hugely here:
I'm sure you'll agree this is not a breaking change. Quite frankly if the current grammar with respect to |
Beta Was this translation helpful? Give feedback.
-
Yes, but it will still be in the minority of existing code.
Generally speaking, you shouldn't have to use intellisense to understand code. If I was in a meeting and someone was projecting that code (or interview and whiteboarding, etc...), my first assumption would not be that
Correct, which is why, given just that line of code. I would (by default) assume it returned
Adding new warnings is a breaking change due to There has been some discussion on fixing this with
Whenever adding a new keyword to an existing language you have to consider a lot of various cases like:
Take: public void MyMethod(ref Guid guidRef)
{
var guid = guidRef; // This results in `Guid guid = guidRef` and not `ref Guid guid = ref guidRef`
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I wrote a generic method which returns " ref T " (T is "unmanaged") and its fine.
However when I call that method with the intention of getting the returned "ref" I must code this:
ref var datum = ref MyMethod<Whatever>(args);
But why? why is the "ref" required after the "=" above? since the method returns a "ref" why can't I just code:
var datum = MyMethod<Whatever>();
I suspect its because C# provides no dereference operator for "ref" values, with pointers we can write *pointer but for ref there is no such thing so how about adding a keyword or something?
If we take out the two "ref" keywords in the above assignment the code compiles but I get a local stack copy of the dereferenced "ref" returned by the method!
I'm arguing that this:
var datum = MyMethod<Whatever>();
should behave exactly like this (if the method returns a "ref")
ref var datum = ref MyMethod<Whatever>(args);
and if I actually wanted a local stack copy of the dereferenced result I should code this:
var datum = val MyMethod<Whatever>();
where "val" is just a suggested keyword that dereferences a ref!
Thoughts?
Beta Was this translation helpful? Give feedback.
All reactions