简体   繁体   中英

C#7 'in' parameters allowed with operator overloading

The recent additions to C# 7 are great and now in the latest release we can pass ValueType ( struct ) instances to functions by-reference ( 'by-ref' ) more efficiently by using the new in keyword.

Using either in or ref in the method declaration means that you avoid the extra 'memory-blt' copy of the entire struct which is normally required in order to preserve by-value semantics. With in , you get this benefit (passing a pointer to the source ValueType itself), but unlike ref , the callee won't be allowed to modify that target (enforcement by the compiler).

In addition to improving the rigor of design intent, in has an added benefit over ref that the call-site syntax is more relaxed than with ref . In fact, you don't need to mention the in keyword at the call-site; it's optional.

Anyway, I noticed that apparently you can define C# operator overloads using in -attributed arguments.

public static bool operator ==(in FILE_ID_INFO x, in FILE_ID_INFO y) => eq(in x, in y);
//       works:            -----^            -----^

This is great if the by-ref semantics actually do prevail in the runtime behavior. But I would find that surprising, because even though C# lets you omit the in keyword in method calls, the generated code at the call site does need to be different. Namely, it needs to emit (eg) OpCodes.Ldflda instead of OpCodes.Ldfld , and so forth.

And then there's also the fact that operator overloads don't have a traditional method "call site" that could be decorated with the (albeit, optional) in keyword:

var fid1 = default(FILE_ID_INFO);
var fid2 = default(FILE_ID_INFO);

bool q =    fid1 ==    fid2;
//       ^--- in? ---^      

So, does anyone know if the compiler, JIT, and runtime will honor what the code seems to be allowed to express, such that calls to operator overloads with in -parameters will actually obtain by-ref semantics? I couldn't find any mention of the situation in the docs. Since the code shown above basically continues to work as it did without the in markings, I suppose the alternative would be that the in keyword is just silently ignored here?

Short answer: The compiler does the right thing. Trust the compiler.

Long answer:

An overloaded operator is simply a syntactic sugar for a static method. An invocation of an overloaded operator is simply a syntactic sugar for an invocation of that method.

That is,

public static bool operator ==(S s1, S s2) { ... }

is just a syntactic sugar for something like

public static bool op_Equality(S s1, S s2) { ... }

and

if (s1 == s2)

is just a syntactic sugar for

if (S.op_Equality(s1, s2))

So whatever behaviour holds for in annotations on normal static methods and normal static method calls also holds for static methods which are operators, and static method invocations which are expressions that use those operators.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM