Replies: 12 comments
-
What advantage does this have over simply documenting the existing language features? Specifically:
|
Beta Was this translation helpful? Give feedback.
-
It doesn't "unlock" new CLR features, but makes existing ones more usable, clean, and easier to understand. It is harder to explain that "TypedReference describes objects that contain both a managed pointer to a location and a runtime representation of the type that may be stored at that location" than explaining that " One could also ask why there is |
Beta Was this translation helpful? Give feedback.
-
Isn't the proper solution here to add better support for casting open generic types so that the object cast isn't necessary? Furthermore, doesn't the JITter optimize out the |
Beta Was this translation helpful? Give feedback.
-
This proposal makes sense, however, I don't like this static void Method(ref AnyReference ar) ... |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@jnm2 god, I have completely forgot about it... Well, still weird, because IIRC with |
Beta Was this translation helpful? Give feedback.
-
Would be nice if flow anaylsis allowed a type check as a type validator; so this was valid static void Method<T>(ref T r)
{
if (typeof(T) == typeof(int))
{
r = 42;
}
else if (typeof(T) == typeof(string))
{
r = "42";
}
} However |
Beta Was this translation helpful? Give feedback.
-
If you're getting into reflecting against generic types, is boxing not the least of your worries at that point? How many use cases would practically benefit from avoiding boxing during reflection calls, and is it worth the cost to implement a new syntax for those few scenarios? I agree with the flow analysis suggestion though, that would really clean up a lot of code in the projects I work on :) |
Beta Was this translation helpful? Give feedback.
-
If you are setting a struct's value using reflection I'm not necessarily agreeing with the proposed syntax; but the existing C# keywords |
Beta Was this translation helpful? Give feedback.
-
You can use static void Method<T>(ref T r)
{
Type t = typeof(T);
if (t == typeof(int))
{
Unsafe.As<T, int>(ref r) = 42;
}
else if (t == typeof(string))
{
Unsafe.As<T, string>(ref r) = "42";
}
} |
Beta Was this translation helpful? Give feedback.
-
You're right that |
Beta Was this translation helpful? Give feedback.
-
Could just keep it similar without the static void Method(TypedReference r)
{
Type t = __reftype(r);
if (t == typeof(int))
{
__refvalue(r, int) = 42;
}
else if(t == typeof(string))
{
__refvalue(r, string) = "42";
}
} But allow static void Method(TypedReference r)
{
Type t = TypedReference.GetTargetType(r);
if (t == typeof(int))
{
(int)r = 42;
}
else if (t == typeof(string))
{
(string)r = "42";
}
} And/Or better would probably be pattern matching with static void Method(TypedReference r)
{
if (r is ref int i)
{
i = 42;
}
else if (r is ref string s)
{
s = "42";
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Since TypedReference has been once again added to the .NET Standard, there should be better ways of working with it than having to resolve to undocumented keywords, especially since a potentially upcoming high-performance reflection API might be using it.
I propose adding a ref-like syntax that compiles to TypedReference, together with ways to use the
mkrefany
andrefanyval
CIL opcodes (undocumented__makeref
and__refvalue
).References with generic types aren't always applicable, or need slow workarounds in some cases:
Here,
r
cannot be directly assigned a value even when we are perfectly sure of its type, and there is no syntax for casting references. If one wishes not to have to box the assigned value, one can use a TypedReference:I propose a new, more elegant syntax for specifying TypedReference variables and their operations:
Here,
ref void
indicates that the parameter is definitely a reference, but with an unknown type (akin tovoid*
). It could be called a "generic reference", and this would also easily explain the limitations of using TypedReference. This code would be compiled to the same CIL as the previous one (maybe with a custom attribute to indicate thatref void
is preferred for the parameter).A generic reference has similar semantics and limitations to a concrete reference (rules for creating variables, passing to and returning from methods, present only on the stack etc.) but with an additional operation of "casting".
(T)r
for aref void r
would mean basically the same as__refvalue(r, T)
means forTypedReference r
. It would represent a reference to a variable with a concrete type, as if the original reference would be declared asref T r
. Therefore, a syntax likeref int i = ref (int)r;
should be also allowed.Creating a generic reference would be an analogue to
__makeref
, and would have the same rules as normal references do.__reftype
has been used for obtaining the actual type of the reference, and although there could also be a new syntax for it (typeof
maybe?), using TypedReference.GetTargetType is sufficient. For checking the type of the reference, a syntax liker is T
would be neat, but not necessary.For compatibility with older code, the original undocumented keywords should be still allowed, but only on variables that are explicitly
TypedReference
, e.g.__refvalue(r, int) = 0;
should not be possible for aref void r
. Generic references and TypedReference wouldn't be mutually compatible, with the only exception of methods that accept or return such references. A way to "cast"ref void r
to a TypedReference could be via__makeref(ref r)
, and something likeref __refvalue(tr, void)
for the opposite.This proposal requires no new .NET API or CLR changes (maybe apart from being able to return a TypedReference, which should have already been allowed).
Beta Was this translation helpful? Give feedback.
All reactions