Description
Currently expressions represents ref
types only in one place, viz. ParameterExpression
objects for which IsByRef
is true.
With a greater use of ref
types due to greater language support, it seems fruitful to increase the availability of ref
types in other expressions. While allowing such types directly on expressions' Type
would be one reasonable approach (so that e.g. exp.Type == typeof(int).MakeByRefType()
could be true) this has two problems:
- It doesn't play well with generics, and while generics aren't used in the typing of most expressions, they are important for the type of lambdas, so keeping ref-ness separate is probably cleaner.
- (More serious of the two, IMO). Doing this would not blend well with the current implementation of
ParameterExpression
.
There is also metadata support for ref
types for which the address should not be written through (in
parameters and ref readonly
variables and returns in C#). It would be useful to be able to express this in expressions.
Note that #24621 would require such ref
support as a prerequisite to making it available to Microsoft.CSharp.
This proposal suggests adding a IsByRef
property to Expression
similar to that of ParameterExpression
(which would hide it in that case, but should return the save value) to represent ref
types and an IsByRefReadOnly
property to represent in
/ref readonly
types.
The default implementation is given as part of the proposal as that would affect custom classes derived from Expression
.
IsByRefReadOnly
only varies in the case where IsByRef
is true. If IsByRef
is false then IsByRefReadOnly
should always be false.
GetDelegateType
would need at least an internal overload that indicated the readonly quality of in
parameters and ref readonly
returns, so it should probably be made public.
The Parameter
factory would similarly need to be able to indicate in
parameters.
Other factories will depend on inferring such types, unless experience shows that explicit factories are beneficial.
namespace System.Linq.Expressions
{
public partial class Expression
{
public static Type GetDelegateType(Type[] typeArgs, bool[] isReadOnlyRef);
public virtual bool IsByRef { get; }
public virtual bool IsByRefReadOnly { get; }
public static ParameterExpression Parameter(Type type, bool isReadOnlyRef);
public static ParameterExpression Parameter(Type type, bool isReadOnlyRef, string name);
}
public class ParameterExpression : Expression
{
public new bool IsByRef { get; } // new added to prevent CS0108
}
}