What is the point of the in modifier for classes - c#

C# 7.2 introduces the in modifier for parameters which makes perfect sense for structs and in particular for readonly structs.
It is also allowed to use it for a reference type
void Method(in StringBuilder value) { }
As reference types are passed by reference by default, is the in in the example above just a redundant modifier?
value = null is forbidden when you use in, does it mean that it spares also the copy of the reference address by just passing the original reference to the heap location and blocking changes?

in is compiled to IL in exactly the same way as ref, except in argument is marked with IsReadOnly attribute.
That means in behaves exactly as ref, but compiler (not runtime) enforces that you don't assign value to in argument.
So, as you correctly pointed out - in referenece-type argument is passed by reference (which means reference is not copied and points to original location), but compiler prevents you from changing it. I don't really see much use for it for reference types, but it won't hurt to have that, at least for consistency.

Whilst the other two answers are correct that in parameters end up as ref parameters in the resultant IL, care should be taken with the claim that this prevents the value being copied. This only holds true for readonly structs.
To demonstrate this, consider the following piece of code:
using System;
public struct S1
{
public int A;
public void ChangeA(int a) => A = a;
}
public static class Program
{
static void Main()
{
var s1 = new S1 { A = 1 };
S1Foo(in s1);
Console.WriteLine(s1.A);
}
private static void S1Foo(in S1 s) => s.ChangeA(2);
}
Since we are passing s1 by reference, one might reasonably assume that S1Foo, in calling ChangeA would then change the contents of s1. This doesn't happen though. The reason being that the s1 value is copied and a copy is passed by reference, to prevent such modifications of structs via in parameters.
If we decompile the resultant IL, you see that the code ends up as:
public static class Program
{
private static void Main()
{
S1 s = default(S1);
s.A = 1;
S1 s2 = s;
Program.S1Foo(ref s2);
Console.WriteLine(s2.A);
}
private static void S1Foo([IsReadOnly] [In] ref S1 s)
{
S1 s2 = s;
s2.ChangeA(2);
}
}
However, if we write similar code using a readonly struct, then no copying occurs. I say similar as it isn't possible to write the same code as fields and property have to be readonly in a readonly struct (the clue is in the name):
using System;
public readonly struct S2
{
private readonly int _a;
public int A => _a;
public S2(int a) => _a = a;
public void ChangeA(int a) { }
}
public static class Program
{
static void Main()
{
var s2 = new S2(1);
S2Foo(in s2);
Console.WriteLine(s2.A);
}
private static void S2Foo(in S2 s) => s.ChangeA(2);
}
Then no copy occurs in the resultant IL.
So in summary:
in is effectively a readonly ref,
The value (or reference) is passed by reference,
The compiler prevents modifying fields and properties of that reference to help enforce its readonly-ness,
To further enforce the readonly nature of the parameter, then non-readonly structs are copied before a reference to the copy is passed to the method. This doesn't occur for readonly structs.

From what I understand from official documentation, it means that arguments passed to the method will not be changed inside the method itself:
The in keyword specifies that you are passing the parameter by reference and the called method does not modify the value passed to it.
when using the in keyword with value types, it means that instead of passing the argument by value (meaning creating a new copy of the value), it is passed by reference - so it avoids the unnecessary copying.

The only useful thing I can think of for in with reference types would be generic functions with constraints.
public interface IIntContainer
{
int Value { get; }
}
public readonly struct LargeStruct : IIntContainer
{
public readonly int val0;
public readonly int val1;
// ... lots of other fields
public readonly int val20;
public int Value => val0;
}
public class SmallClass : IIntContainer
{
public int val0;
public int Value => val0;
}
public static class Program
{
static void Main()
{
DoSomethingWithValue(new LargeStruct());
DoSomethingWithValue(new SmallClass());
}
public static void DoSomethingWithValue<T>(in T container) where T : IIntContainer
{
int value = container.Value;
// Do something with value...
}
}

Related

Why are we allowed to use const with reference types if we may only assign null to them?

The question is actually very straightforward. The following code throws the exception right below it:
class Foo
{
public const StringBuilder BarBuilder = new StringBuilder();
public Foo(){
}
}
Error:
Foo.BarBuilder' is of type 'System.Text.StringBuilder'. A const field
of a reference type other than string can only be initialized with
null.
MSDN says this, which I understand and it makes sense from const perspective:
A constant expression is an expression that can be fully evaluated at
compile time. Therefore, the only possible values for constants of
reference types are string and a null reference.
However, I don't see the reason why or where we would use null constant. So why in the first place that a reference type (other than string) can be defined with const if it can be only set to null and if it was a deliberate decision (which I believe it is) then where can we use constant with null values?
Update:
When we think of an answer, please let's think differently than "We have this so why not that..." context.
From MSDN
when the compiler encounters a constant identifier in C# source code (for example, months), it substitutes the literal value directly into the intermediate language (IL) code that it produces. Because there is no variable address associated with a constant at run time, const fields cannot be passed by reference and cannot appear as an l-value in an expression.
Because reference types (other than null, and strings which are special) need to be constructed at run time, the above would not be possible for reference types.
For reference types, the closest you can get is static readonly:
class Foo
{
// This is not a good idea to expose a public non-pure field
public static readonly StringBuilder BarBuilder = new StringBuilder();
public Foo(){
}
}
Unlike const substitution (in the calling code), static readonly creates a single shared instance of the reference type which has subtle differences if assembly versions are changed.
Although the reference cannot (normally) be reassigned, it doesn't preclude calling non-pure methods on the StringBuilder (like Append etc). This is unlike consts, where value types and strings are immutable (and arguably should be "eternal").
However, I don't see the reason why or where we would use null constant.
Null constants are useful as sentinel values.
For example, this:
public class MyClass
{
private const Action AlreadyInvoked = null;
private Action _action;
public MyClass(Action action) {
_action = action;
}
public void SomeMethod()
{
_action();
_action = AlreadyInvoked;
}
public void SomeOtherMethod()
{
if(action == AlreadyInvoked)
{
//...
}
}
}
Is much more expressive than this:
public class MyClass
{
//...
public void SomeMethod()
{
_action();
_action = null;
}
public void SomeOtherMethod()
{
if(action == null)
{
//...
}
}
}
The source code for the Lazy<T> class shows Microsoft used a similar strategy. Although they used a static readonly delegate that can never be invoked as a sentinel value, they could have just used a null constant instead:
static readonly Func<T> ALREADY_INVOKED_SENTINEL = delegate
{
Contract.Assert(false, "ALREADY_INVOKED_SENTINEL should never be invoked.");
return default(T);
};
As you state in the question, there is one reference type that can be put into a const reference - strings. The compiler special-cases this and puts the strings into the compiled output and allows them to be read into the reference type at runtime.
Of course this begs the question - why not have strings be the only reference types that can be const, as long as we're special-casing them anyway? To that, I can only speculate that adding a special case in the compiler is simpler and less problematic than adding a special case in the language. From a language perspective, a string is just a reference type, even if the compiler has special handling to create instances of it from string literals and compiled resources.
I think that you are asking that why reference type with null allow as a constant.
I think you are right that it does not make much sense but it is useful if you have designed your own library and if you want to compare with null but want to give special meaning ( like comparing with your library value only rather then directly null)
public class MyClass
{
public const MyClass MyClassNull = null;
public MyClass()
{
}
}
it usage like this.
object obj = GetMyClass();
if(obj == MyClass.MyClassNull) // This going to convert to actual null in MSIL.
{
}

Can "ref" be used as a persistent link between classes?

I have one instance of ClassA that is passed as a ref to constructor of ClassB. Does the instance of ClassB now always have the access to the newest updated version of the passed instance of ClassA?
public class ClassA {
private int variableA = 0;
public ClassA() { }
public void Change(int newValue) {
variableA = newValue;
}
}
public class ClassB {
public ClassA classA;
public ClassB(ref ClassA refClassA) {
classA = refClassA;
}
public void Print() {
Console.WriteLine(classA.variableA);
}
}
static void Main() {
ClassA classA = new ClassA();
ClassB classB = new ClassB(ref classA);
classB.Print(); // 0
classA.Change(50);
classB.Print(); // 50?
}
I've read what I found on the internet but the only usage I've found was to update the referenced value, like in dotnetperls http://www.dotnetperls.com/ref .
That is not what ref is for, the same behavior is achieved without it.
You don't need the ref keyword here. Even without it, ClassB will hold a reference to ClassA, rather than a copy of its values.
Note that your code won't work because variableA is private, so ClassB can't access it in its Print method. Other than that, though, the output would be as you expected in your example
ref has nothing to do with persistence. It only means that you can change the value of the original variable. If you call a method without ref, the method can assign that variable whatever they want and the caller's variable doesn't change. With ref, the caller will also point to another place.
Simple example:
void Call(int x)
{
x = 2;
}
void CallRef(ref int x)
{
x = 10;
}
int a=0;
Call(a); // a is still 0
CallRef(ref a); // a is 10
Yes it does. But it is not even needed since objects are always pointers and the ref keyword is used to pass the pointer of non objects to functions (e.g: int, float, structs, etc.)
Yes, it has the reference to it. It means that it does not save the values of the elements of ClassA but rather just its address in the memory (on the heap).
Therefore, make sure you do not reinstantiate classA:
classA.change(50) will work but classA = new ClassA() will not.
Also, please note that reference types (such as classes) do not need the ref keyword, they are automatically handled that way.
If you want to have access to the last instance of ClassA you can wrap your variable with a class like this:
public class Ref<T>
{
readonly Func<T> getter;
readonly Action<T> setter;
public T Value
{
get
{
return getter();
}
set
{
setter(value);
}
}
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
}
Then modify your ClassB like this:
public class ClassB
{
readonly Ref<ClassA> refClassA;
public ClassA ClassA
{
get
{
return refClassA.Value;
}
}
public ClassB(Ref<ClassA> refClassA)
{
this.refClassA = refClassA;
}
public void Print()
{
Console.WriteLine(ClassA.VariableA);
}
}
Then you can test and see if you have the behavior desired:
var a = new ClassA(1);
var b = new ClassB2(new Ref<ClassA>(() => a, x => a = x));
b.Print(); // output 1
var c = a; // backup old reference
a = new ClassA(2);
b.Print(); // output 2
// b stores old instance of a?
Console.WriteLine(object.ReferenceEquals(b.ClassA, c)); // output false
// a stores new instance of a?
Console.WriteLine(object.ReferenceEquals(b.ClassA, a)); // output true
I assume you wnat something like this, keep in mind that is a draft, so you have to work a lot.
EDIT
I had stolen the Ref<T> class from an blog of Eric Lippert, finally i found this SO question where he posted it.

Is a string reference equality check guaranteed to be static?

I have a function with this signature:
public void DoSomething(String name);
The string name is special in my application. It can be either an arbitrary string, or a special known value. Because any non-empty string value is a valid input it means I need to use object reference equality with empty strings, like so:
public class Foo {
public const String SpecialValue1 = "";
public const String SpecialValue2 = "";
public void DoSomething(String name) {
if( Object.ReferenceEquals( name, SpecialValue1 ) ) {
} else if( Object.ReferenceEquals( name, SpecialValue2 ) {
} else {
}
}
public void UsageExample() {
DoSomething( SpecialValue1 );
DoSomething( "some arbitrary value" );
}
}
I want to know if this technique, using empty strings and object reference equality will always be safe, especially with respect to string interning.
Antimony is right about the reasons this will not work.
I would suggest that you define a type for the argument. Let's call it ExampleArgument.
public class ExampleArgument
{
private readonly int _knownValue;
private readonly string _arbitraryValue;
public ExampleArgument(string arbitraryValue)
{
_arbitraryValue = arbitraryValue;
_knownValue = 0;
}
private ExampleArgument(int knownValue)
{
_knownValue = knownValue;
_arbitraryValue = null;
}
public static readonly ExampleArgument FirstKnownValue = new ExampleArgument(1);
public static readonly ExampleArgument SecondKnownValue = new ExampleArgument(2);
// obvious Equals and GetHashCode overloads
// possibly other useful methods that depend on the application
}
Oh, and if you really want the calling syntax in your example, you could add:
public static implicit operator ExampleArgument(string arbitraryValue)
{
return new ExampleArgument(arbitraryValue);
}
Which is an implicit conversion operator from string to ExampleArgument.
DoSomething(ExampleArgument.FirstKnownValue);
DoSomething(new ExampleArgument("hello"));
DoSomething("hello"); // equivalent to previous line, uses implicit conversion operator
No, this is not safe. In fact, this will never work. String literals get interned, so both special values will have the same reference. Most compilers will also intern compile time constant strings, and you can always intern strings manually.
Unfortunately, if you want to accept any valid string, you need some other way to pass extra information. And even if a hack like this worked, it would be a bad idea, since it violates normal string equality semantics.
Here are the possibilities I can think of
If you only have one special value, you can use null
Take a broader type such as Object as input
Take two parameters
Make a separate function

Explicitly refer to a parameter

How do I explicitly refer to the parameter as opposed to the member variable?
static recursive{
public static List<string> output = new List<string>();
public static void Recursive(List<string> output){
...
}
}
An unqualified reference will always refer to the parameter because it is at a more local scope.
If you want to refer to the member variable, you need to qualify it with the name of the class (or this, for non-static member variables).
output = foo; // refers to the parameter
recursive.output = foo; // refers to a static member variable
this.output = foo; // refers to a non-static member variable
But you should probably change the name anyway. It makes your code much easier to read.
And you shouldn't have public static variables at all. All of the .NET coding style guidelines strongly recommend properties instead of exposing public fields. And since those are always camel-cased, this problem solves itself.
public static void Recursive(List<string> output){
...
}
The code in the block that refers to output will always be local & not the member variable.
If you wish to refer to member variable, you could use recursive.output.
When you are inside the Recursive static method output will point to the argument of the method. If you want to point to the static field use the name of the static class as prefix: recursive.output
Give your member variable another name.
The convention is to use Camelcasing on public static members.
public static List<string> Output = new List<string>();
public static void Recursive( List<string> output )
{
Output = output;
}
You can explicitly reference recursive.output to indicate the static member, but it would be cleaner to rename either the parameter or the member.
I know of no way to explicitly refer to a parameter. The way this is usually handled is to give member variables a special prefix such as _ or m_ so that parameters will never have exactly the same name. The other way is to refer to member variables using this.var.
public class MyClass {
public int number = 15;
public void DoSomething(int number) {
Console.WriteLine(this.number); // prints value of "MyClass.number"
Console.WriteLine(number); // prints value of "number" parameter
}
}
EDIT::
For static fields is required name of class instead of "this":
public class MyClass {
public static int number = 15;
public void DoSomething(int number) {
Console.WriteLine(this.number); // prints value of "MyClass.number"
Console.WriteLine(MyClass.number); // prints value of "number" parameter
}
}

Store a reference to a value type?

I am writing a "Monitor" object to facilitate debugging of my app. This Monitor object can be accessed at run time from an IronPython interpreter. My question is, is it possible in C# to store a reference to a value type? Say I have the following class:
class Test
{
public int a;
}
Can I somehow store a "pointer" to "a" in order to be able to check it's value anytime? Is it possible using safe and managed code?
Thanks.
You cannot store a reference to a variable in a field or array. The CLR requires that a reference to a variable be in (1) a formal parameter, (2) a local, or (3) the return type of a method. C# supports (1) but not the other two.
(ASIDE: It is possible for C# to support the other two; in fact I have written a prototype compiler that does implement those features. It's pretty neat. (See http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ for details.) Of course one has to write an algorithm that verifies that no ref local could possibly be referring to a local that was on a now-destroyed stack frame, which gets a bit tricky, but its doable. Perhaps we will support this in a hypothetical future version of the language. (UPDATE: It was added to C# 7!))
However, you can make a variable have arbitrarily long lifetime, by putting it in a field or array. If what you need is a "reference" in the sense of "I need to store an alias to an arbitrary variable", then, no. But if what you need is a reference in the sense of "I need a magic token that lets me read and write a particular variable", then just use a delegate, or a pair of delegates.
sealed class Ref<T>
{
private Func<T> getter;
private Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value
{
get { return getter(); }
set { setter(value); }
}
}
...
Ref<string> M()
{
string x = "hello";
Ref<string> rx = new Ref<string>(()=>x, v=>{x=v;});
rx.Value = "goodbye";
Console.WriteLine(x); // goodbye
return rx;
}
The outer local variable x will stay alive at least until rx is reclaimed.
No - you can't store a "pointer" to a value type directly in C#.
Typically, you'd hold a reference to the Test instance containing "a" - this gives you access to a (via testInstance.a).
Here is a pattern I came up with that I find myself using quite a bit. Usually in the case of passing properties as parameters for use on any object of the parent type, but it works just as well for a single instance. (doesn't work for local scope value types tho)
public interface IValuePointer<T>
{
T Value { get; set; }
}
public class ValuePointer<TParent, TType> : IValuePointer<TType>
{
private readonly TParent _instance;
private readonly Func<TParent, TType> _propertyExpression;
private readonly PropertyInfo _propInfo;
private readonly FieldInfo _fieldInfo;
public ValuePointer(TParent instance,
Expression<Func<TParent, TType>> propertyExpression)
{
_instance = instance;
_propertyExpression = propertyExpression.Compile();
_propInfo = ((MemberExpression)(propertyExpression).Body).Member as PropertyInfo;
_fieldInfo = ((MemberExpression)(propertyExpression).Body).Member as FieldInfo;
}
public TType Value
{
get { return _propertyExpression.Invoke(_instance); }
set
{
if (_fieldInfo != null)
{
_fieldInfo.SetValue(_instance, value);
return;
}
_propInfo.SetValue(_instance, value, null);
}
}
}
This can then be used like so
class Test
{
public int a;
}
void Main()
{
Test testInstance = new Test();
var pointer = new ValuePointer(testInstance,x=> x.a);
testInstance.a = 5;
int copyOfValue = pointer.Value;
pointer.Value = 6;
}
Notice the interface with a more limited set of template arguments, this allows you to pass the pointer to something that has no knowledge of the parent type.
You could even implement another interface with no template arguments that calls .ToString on any value type (don't forget the null check first)
You can create ref-return delegate. This is similar to Erik's solution, except instead of getter and setter it use single ref-returning delegate.
You can't use it with properties or local variables, but it returns true reference (not just copy).
public delegate ref T Ref<T>();
class Test
{
public int a;
}
static Ref<int> M()
{
Test t = new Test();
t.a = 10;
Ref<int> rx = () => ref t.a;
rx() = 5;
Console.WriteLine(t.a); // 5
return rx;
}
You can literally take a pointer to a value type using usafe code
public class Foo
{
public int a;
}
unsafe static class Program
{
static void Main(string[] args)
{
var f=new Foo() { a=1 };
// f.a = 1
fixed(int* ptr=&f.a)
{
*ptr=2;
}
// f.a = 2
}
}
class Test
{
private int a;
/// <summary>
/// points to my variable type interger,
/// where the identifier is named 'a'.
/// </summary>
public int A
{
get { return a; }
set { a = value; }
}
}
Why put yourself through all that hassle of writing complicated code, declaring identifiers everywhere linking to the same location? Make a property, add some XML code to help you outside the class, and use the properties in your coding.
I don't know about storing a pointer, don't think it's possible, but if you're just wanting to check its value, the safest way to my knowledge is to create a property of the variable. At least that way you can check its property at any time and if the variable is static, you wouldn't even have to create an instance of the class to access the variable.
Properties have a lot of advantages; type safety is one, XML tags another. Start using them!

Categories