Reputation: 405
Earlier this week, C# 7.2 was released with the new feature of "in" parameter modifier see release notes here
The details provided in the release notes are:"The in modifier on parameters, to specify that an argument is passed by reference but not modified by the called method."
There is not a lot of documentation out on this new feature yet, so I have been trying it out. Seems to work as expected for primitive types, and prevents access to object properties. However, for lists you can still call the methods to modify a List (i.e. Add, Remove, Reverse) and you can actually modify an element directly.
static void Main(string[] args)
{
var test = new List<int>();
test.Add(5);
Console.WriteLine(test[0]);
TestMethod(test);
Console.WriteLine(test[0]);
}
public static void TestMethod(in List<int> myList)
{
myList[0] = 10;
myList.Add(7);
myList.Remove(2);
}
My question is, why can still modify collections when using the "in" parameter modifier?
Upvotes: 1
Views: 663
Reputation: 27039
These points from the documentation really clarifies the intent of the in
modifier:
There are several ways in which the compiler ensures that the read-only nature of an in argument is enforced. First of all, the called method can't directly assign to an in parameter.
Ok so that means we cannot do this:
public void Something(in Point3D point1)
{
point1 = new Point3D(); // not allowed
}
It can't directly assign to any field of an in parameter.
Ok so that means we cannot do this as well:
public void Something(in Point3D point1)
{
point1.X = 10; // not allowed
}
In addition, you cannot pass an in parameter to any method demanding the ref or out modifier.
Ok so that means we cannot do below as well for obvious reasons because the method we are calling can set the reference which will break the above first rule:
public void Something(in Point3D point1)
{
SomethingElse(ref point1); // not allowed
}
public void SomethingElse(ref Point3D pointAnother)
{}
The compiler enforces that the in argument is a readonly variable. You can call any instance method that uses pass-by-value semantics. In those instances, a copy of the in parameter is created. Because the compiler can create a temporary variable for any in parameter, you can also specify default values for any in parameter.
So what I gather from the above is that you can pass a List<T>
and the called method will be able to add items to it but it will not be able to assign another list to it or changes it's fields.
In Conclusion
Why can you still modify a List<> when it has the “in” parameter modifier in C# 7.2
You are allowed to do that because you are not breaking any of the rules.
Upvotes: 1
Reputation: 190986
The in
modifier only restricts assigning to the reference, but the List<T>
is still accessible and mutable. Basically it works like ref readonly
.
You can't do myList = new List<int>
.
Upvotes: 7