What’s this 'in' in C#?

Asked

Viewed 449 times

12

In the new version of C#, version 7.3 the parameter changer was introduced in, but I didn’t understand its functionality.

By name, it seems that it is used as "input" for the values, contrary to the out does. I know that the out does the following:

string variavelNulaNaDeclaracao = null;
Alterar(out variavelNulaNaDeclaracao);

void Alterar(out string data) => data = "Olá, mundo!";

then, variavelNulaNaDeclaracao will be "Hello world" even being null in the statement. But what about the in? I just understood that it also serves to change the signature of the methods and create an Overload between them, other than that, I found no other utilities.

void Funcao(int x, int y) { ... }
void Funcao(in int x, in int y) { ... }

What good is that in? To pass only the value of a variable? Or the entire reference? It will discard the use of ref?

1 answer

16


You know what the ref and knows what the readonly? Well, it’s a junction of the two.

So you’re saying you’re going to pass a value as a reference, instead of copying the value to another variable, so what’s copied is the address where the value is (this is a reference), and this parameter (which is still a variable) will be read-only, which means that you cannot change the referenced value, so it is a parameter that guarantees a contract (promises) that the value will be immutable there inside.

Unlike out and ref which only relate to variables as an argument, the in accepts literals or expressions, because it only needs the value, the result will not be stored.

See more about types by value and reference in Memory allocation in C# - Value types and reference types and What’s the difference between Struct and Class?.

What is the most fundamental difference between a class and a structure? The first is always by reference and the second is always by value. In C#, at the moment, it also occurs that classes are always in the heap (but this may not be true in the future, even with constraints), structures may be in several places, but if they are local they will always be in the stack (except for an optimization that puts it in the processor register or a upvalue because of a closure or something like that that heap circumstantially).

What’s the big problem with classes? It allocates to heap and is subject to garbage collection. So it helps to fill the memory manager and causes pauses and extra processing of the GC. We must try to prevent the Garbage Collector work hard to be very efficient. So better not to use them, right? The problem is that some values do not work well as types per value for a number of reasons that I think is not the case here, but for the most part is already answered in the questions linked above. How to have a type by reference without allocating in heap and harm GC? C# 7.x is about this, especially 7.2.

He created the ref struct where it requires the type to be by reference, but maintains the ability to be in the stack. It’s just common for guys like that to be immutable, so there’s ref readonly struct, or even the readonly struct only to ensure the immutability of the normal structure.

Can create a struct characteristic of a class and use as if it were one, but allocating in the stack, and safely to the intent. This site here uses techniques like this, but it is complicated to do right, have to take care and is not recommended for those who are not too advanced. It is easier with 7.2 (not 7.3), although it still requires understanding of what you are doing.

Turns out you don’t always have it ready, it doesn’t make sense, you might want to use a in which originally is a struct unseen ref.

Many times the ref for this. The problem is that you could change the value, even inadvertently. And the idea of the ref actually is to change its value (which was most needed when there were no tuples), you use when you need it. As well as the out which is useful to return a value by argument, and which is better because it is optimized, goes in only one direction, including there is a guarantee that there is no value in the input.

The in then allows to pass by reference (it is called aliasing) ensuring that the value does not change, so there is no back, can be optimized, whether by passing a ref readonly struct created like this or if it is only one of the two modifiers, or without any of them. In some cases you avoid allocation as well, especially in cases where the structure needs to have a semantic closer to a class, or mainly with larger size that usually a structure has, but was created as a structure for optimization reasons.

The change in 7.3 is the parameter with in which happened to be different from the parameter without it, so they’re different signatures. But 7.2 now has this also because it was considered that the original behavior was a bug.

The return happened to have something similar.

The in in reference or value types, but simple, such as int, is considered irrelevant or useless, since you will exchange six for half a dozen. The gain will be on top of types per value with more than 16 bytes, and in my experience, in most current platforms, the gain will only be expressive in objects with more than 64 bytes (I think it is by the size of the cache line and how the backend compiler optimizes for some platforms).

  • 1

    For those and others I didn’t answer =D

  • @Jeffersonquesado I will improve, for example :P

  • Congratulations on the well didactic explanation!

  • @ramonritter thanks, but I need to review, I did at dawn, has several writing errors :D

  • @Maniero by default, does C# use access in parameters without any statement malicious? A class passed by parameter without the ref, can have its values changed in memory, or only in the scope of the method?

  • 1

    @Cypherpotato, I don’t know if I fully understand, but by default the argument (https://answall.com/q/32448/101) is passed by value, always. Just note that we have two types of data, one for same value and the other for reference (https://answall.com/q/16181/101). When talking about classes that is by reference normal pass allows changing the object data, directly in it, reflects in every application, but can not change the object as a whole, ie the reference to the object,only can do this c/ o ref.In classes the value is the reference, ref is used p/ pass value by ref.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.