Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are two kinds of types in the C# type system "value types" and "reference types".</p> <p>Value types are copied by value; when you copy one, you get a wholly new object that has nothing to do with the original.</p> <p>Reference types are copied by reference; when you copy one, you are actually copying a reference to some storage location. You get two references that both refer to one object.</p> <p>Shorts are value types.</p> <p>If you want a short to be a reference type, then you could make a reference type wrapper:</p> <pre><code>class ReferenceType&lt;T&gt; where T : struct { public T Value { get; set } public ReferenceType(T value) { this.Value = value; } } var v1 = new ReferenceType&lt;short&gt;(1); var v2 = new ReferenceType&lt;short&gt;(2); var vs = new ReferenceType&lt;short&gt;[2] { v1, v2 }; v1.Value = 1024; v2.Value = 512; Console.WriteLine(vs[0].Value); Console.WriteLine(vs[1].Value); </code></pre> <p>And there you go.</p> <p>Now, that will give you reference access to <em>the short</em> because the short is actually stored in the field associated with the value property of the class. If you then say:</p> <pre><code>v2 = new ReferenceType&lt;short&gt;(3); Console.WriteLine(vs[1].Value); </code></pre> <p>you won't get "3" -- v2 now refers to a different object than vs[1]. If what you <em>really</em> want to capture is a reference to <em>a variable</em> then what you want to use is a <em>closure</em>.</p> <pre><code>class ReferenceToVariable&lt;T&gt; { private Func&lt;T&gt; getter; private Action&lt;T&gt; setter; public ReferenceToVariable(Func&lt;T&gt; getter, Action&lt;T&gt; setter) { this.getter = getter; this.setter = setter; } public T Value { get { return getter(); } set { setter(value); } } } ... short v1 = 1; short v2 = 2; var vs = new [] { new ReferenceToVariable&lt;short&gt;(()=&gt;v1, x=&gt;{v1=x;}), new ReferenceToVariable&lt;short&gt;(()=&gt;v2, x=&gt;{v2=x;}) }; v1 = 123; vs[1].Value = 456; Console.WriteLine(vs[0].Value); // 123 Console.WriteLine(v2); // 456 </code></pre> <p>Here we capture in the array objects which know how to get and set the current values of v1 and v2.</p> <p>Now, if what you want to do is make an <em>alias</em> to another variable <em>directly</em>, without this object in the way, then there is only one way to do that in C#:</p> <pre><code>void M(ref short x) { x = 123; } ... short y = 1; M(ref y); </code></pre> <p>Now "x" and "y" are two names for the same variable. However, the concept of "make an alias to another variable" only works in C# when the aliasing variable is a formal parameter of a method. There is no way to do it in general.</p> <p>Now, we could in theory do something like what you want. We could support "ref locals":</p> <pre><code>short v1 = 1; ref short rv1 = ref v1; rv1 = 123; Console.WriteLine(v1); // 123 </code></pre> <p>That is, rv1 becomes an alias for v1. C# does not support this, but the CLR does and therefore we could support it. However, the CLR does <em>not</em> support making arrays of "ref" element type, or fields that store refs. So in that sense, you couldn't do what you want.</p> <p>C# does support some special "hidden" features for passing around objects that act like references to variables but are lighter weight than the "two delegate" reference mentioned above. However, these special features are only for bizarre interop scenarios and I recommend against them. (And again, you can't make an array that stores typed references.) I don't think I'll talk about those features more in this answer; you really don't want to go there, believe me.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload