I would like to hold references to a number of shorts in an array. I assumed I could just create the shorts and then add them to the array. So... every time the referenced object is changed, this is reflected in the array, and vice versa. Doing some trials convinced me that it does not quite work that way. In fact, it looks like the value is transferred but not a reference.
Below code creates two shorts, adds these to an array as objects, then changes the original short. However, when accessing the assumed referenced short in the array it has not changed, which leads me to believe that it is a wholly new object that has nothing to do with the original one.
Console.WriteLine("Testing simple references:");
short v1 = 1;
short v2 = 2;
object[] vs = new object[2];
vs[0] = v1;
vs[1] = v2;
v1 = 1024;
v2 = 512;
Console.WriteLine(" v1: " + (short)vs[0]);
Console.WriteLine(" v2: " + (short)vs[1]);
I am misunderstanding something fundamental here and would appreciate if someone could explain, and perhaps point me to a solution that would do what I want.
There are two kinds of types in the C# type system "value types" and "reference types".
Value types are copied by value; when you copy one, you get a wholly new object that has nothing to do with the original.
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.
Shorts are value types.
If you want a short to be a reference type, then you could make a reference type wrapper:
class ReferenceType<T> where T : struct
{
public T Value { get; set }
public ReferenceType(T value) { this.Value = value; }
}
var v1 = new ReferenceType<short>(1);
var v2 = new ReferenceType<short>(2);
var vs = new ReferenceType<short>[2] { v1, v2 };
v1.Value = 1024;
v2.Value = 512;
Console.WriteLine(vs[0].Value);
Console.WriteLine(vs[1].Value);
And there you go.
Now, that will give you reference access to the short because the short is actually stored in the field associated with the value property of the class. If you then say:
v2 = new ReferenceType<short>(3);
Console.WriteLine(vs[1].Value);
you won't get "3" -- v2 now refers to a different object than vs[1]. If what you really want to capture is a reference to a variable then what you want to use is a closure.
class ReferenceToVariable<T>
{
private Func<T> getter;
private Action<T> setter;
public ReferenceToVariable(Func<T> getter, Action<T> 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<short>(()=>v1, x=>{v1=x;}),
new ReferenceToVariable<short>(()=>v2, x=>{v2=x;})
};
v1 = 123;
vs[1].Value = 456;
Console.WriteLine(vs[0].Value); // 123
Console.WriteLine(v2); // 456
Here we capture in the array objects which know how to get and set the current values of v1 and v2.
Now, if what you want to do is make an alias to another variable directly, without this object in the way, then there is only one way to do that in C#:
void M(ref short x)
{
x = 123;
}
...
short y = 1;
M(ref y);
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.
Now, we could in theory do something like what you want. We could support "ref locals":
UPDATE: The "theoretical" feature I discuss here was added to C# 7.0.
short v1 = 1;
ref short rv1 = ref v1;
rv1 = 123;
Console.WriteLine(v1); // 123
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 not support making arrays of "ref" element type, or fields that store refs. So in that sense, you couldn't do what you want.
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.
Short is a value type, but you're trying to make it behave like a reference type.
You can create a class with a short property and then use an array of that class:
public class MyShort
{
public short Value {get; set;}
}
public class SomeOtherClass
{
public void SomeMethod()
{
MyShort[] array = new MyShort[2];
array[0] = new MyShort {Value = 5};
array[1] = new MyShort {Value = 2};
array[0].Value = 3;
}
}
There's potentially some work you can do there to make it smoother (like implementing a converter from short to your wrapper class and back).
The short type is a value type and does not work like reference types which behaves like you are expecting your shorts to behave. When you assign a value type to a variable, its value is assigned, not its reference. vs[0] will hold a copy of the value you assigned to v1.
If you really need to have the values in the array change when you change the original value, you need to wrap your short in a reference type. Here is an example:
public class ShortHolder {
public short Value { get; set; }
}
Then you can use it like this:
var v1 = new ShortHolder() { Value=123; }
var shortArray = new ShortHolder[1];
shortArray[0] = v1;
If you change v1.Value, then shortArray[0].Value will also change.
Value types are called value types because they are passed by value when passed to methods or assigned via the = operator.
Another (and more correct) way to look at it is that shorts, ints, etc. are immutable => they cannot be changed. So you basically cannot change a short. If you need an object of type short to change somewhere you need to create a class to hold this object like this:
public class ShortWrapper
{
public short ShortValue {get; set;}
}
class Program
{
static void Main(string[] args)
{
ShortWrapper short1 = new ShortWrapper{ ShortValue = 1};
ShortWrapper short2 = new ShortWrapper { ShortValue = 2 };
ShortWrapper[] shorts = new ShortWrapper[] { short1, short2 };
shorts[0].ShortValue = 5;
Console.WriteLine(short1.ShortValue);
}
}
Essentially the code is replacing the object of type short with a new object.
BTW chances are that there is something wrong with your design if you need to wrap a naked short. You either should be using some more complex object already or should be working with the array of shorts in some other way. But I guess you are just testing.
The fundamental problem is that short is a struct and not an object. So basically an array of short is actually an array of short and not an array of references to short objects.
To solve the problem you can "box" the short in a class (but it's going to be tedious)
Try with the following:
public class MyShort { public Value { get; set; } }
You can use ReferenceType transparently as if float, int etc. were actually reference types if you add a conversion operator to the class:
class ReferenceType<T> where T : struct
{
public T Value { get; set; }
public ReferenceType(T value) { this.Value = value; }
public static implicit operator ReferenceType<T>(T b)
{
ReferenceType<T> r = new ReferenceType<T>(b);
return r;
}
public static implicit operator T(ReferenceType<T> b)
{
return b.Value;
}
}
ReferenceType<float> f1 = new ReferenceType(100f);
f1 = 200f;
float f2 = f1;
By using the explicit qualifier instead of implicit, you can require casts for these conversions, if you want to make things clearer at the expense of a little verbosity.
Related
In C# if I use a struct like shown below and do an equality comparison , values of the fields of the struct would be compared and I would get a result true if all the fields have same value.This is the default behaviour.
struct PersonStruct
{
public PersonStruct(string n,int a)
{
Name = n;Age = a;
}
public string Name { get; set; }
public int Age { get; set; }
}
var p1 = new PersonStruct("Jags", 1);
var p2 = new PersonStruct("Jags", 1);
Console.WriteLine(p1.Equals(p2)); //Return True
In case of class same thing would return a value false as it is a reference type.
class PersonClass
{
public PersonClass(string n, int a)
{
Name = n; Age = a;
}
public string Name { get; set; }
public int Age { get; set; }
}
var pc1 = new PersonClass("Jags", 1);
var pc2 = new PersonClass("Jags", 1);
Console.WriteLine(pc1.Equals(pc2));//Returns False
I understand the above concept.My question is considering the above scenario is it a good idea to use structs in such simple cases instead of a class ? I have commonly seen people implement classes in such cases(e.g. simple DTOs) and do all the extra stuff to implement equality operators (such as IEquatable and overridden equals method) .
Is my understanding correct or am I missing something here ?
You should avoid the default implementation of equality for structs. If your structs contain reference type fields (as PersonStruct does) then reflection is used to compare corresponding fields for equality, which is relatively slow. You should also implement IEquatable<T> for your structs since calling the object.Equals(object) method will cause boxing for both the source and argument struct. This will be avoided if the call can be resolved to IEquatable<PersonStruct>.
There is a whole article about this in MSDN.
✓ CONSIDER defining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.
X AVOID defining a struct unless the type has all of the following characteristics:
It logically represents a single value, similar to primitive types (int, double, etc.).
It has an instance size under 16 bytes.
It is immutable.
It will not have to be boxed frequently.
In all other cases, you should define your types as classes.
Related:
When do you use a struct instead of a class?
I have a static double variable in a static class. When I create a specific class, I use the double variable as one of the args of the constructor. What would be the easiest way of manipulating field of the object by changing the variable in static class.
Code for clarity:
public static class Vars
{
public static double Double1 = 5.0;
}
public class ClassFoo
{
public double Field1;
public ClassFoo(double number)
{
Field1 = number;
}
}
class Program
{
static void Main(string[] args)
{
ClassFoo Foo = new ClassFoo(Vars.Double1);
Console.WriteLine(Foo.Field1 + " " + Vars.Double1); //5 5
Vars.Double1 = 0.0;
Console.WriteLine(Foo.Field1 + " " + Vars.Double1); //5 0
//Foo.Field1 need to be a reference to Vars.Double1
}
}
EDIT that goes beyond the question (no more answers needed, other solution found):
I change some values (fields) very often (at runtime, or at least i would like to change them at runtime) to look for one that is right for me. Implementing:
if(KeyDown)
variable++;
if(OtherKeyDown)
variable--;
Wasn't convenient enough. I just checked Visual Studio Debugger. It's not good (fast) enough. Have to pause, change and run code code again. Method i presented would be good if changed static variable would change field of the object.
In short: no, you can't do this... at least, not seamlessly.
As noted, this is generally considered to be A Bad Idea™. There is no reference encapsulation for value types, and no simple way to implement a seamless wrapper class to do it because you can't overload the assignment operators. You can use the techniques from the Nullable<T> type to get part-way there, but no further.
The big stumbling block is the assignment operator. For the Nullable type this is fine. Since it is non-referencing (new values are distinct), an implicit conversion operator is sufficient. For a referencing type you need to be able to overload the assignment operator to ensure that assignment changes the contained data instead of replacing the wrapper instance.
About the closest you can get to full reference is something like this:
public class Refable<T> where T : struct
{
public T Value { get; set; }
public Refable(T initial = default(T))
{
Value = initial;
}
public static implicit operator T(Refable<T> self)
{
return self.Value;
}
}
This will hold a value of the specific type, will automatically convert to that type where applicable (Refable<double> will implicitly convert to double when required for instance), but all assignments must be done by referencing the Value property.
Example usage:
Refable<double> rd1 = new Refable<double>(1.5);
Refable<double> rd2 = d1;
// get initial value
double d1 = rd1;
// set value to 2.5 via second reference
rd2.Value = 2.5;
// get current value
double d2 = rd1;
// Output should be: 1.5, 2.5
Console.WriteLine("{0}, {1}", d1, d2);
What you really want to do is have Vars be a regular class, not a static class. For all methods and classes that need to deal with the variables contained in Vars, you can pass in a reference to that Vars instance.
Here is a very simple example program that illustrates the above. Note that you could probably do a lot to improve the design of your program, but this will at least get you going in the right direction, and away from trying to bend the language to do things it can't or shouldn't do.
public class SharedVars {
public static double Foo = 0.0;
}
public class ClassFoo {
private SharedVars mySharedVars;
public ClassFoo(SharedVars sharedVars) {
// save a reference to the shared variables container class for future use
mySharedVars = sharedVars;
}
// here's an example use
public void ProcessKeyDown() {
mySharedVars.foo++;
}
}
class Program {
static void Main(string[] args) {
SharedVars sharedVars = new SharedVars();
ClassFoo foo = new ClassFoo(sharedVars);
// ... some stuff happens ...
if(KeyDown)
foo.ProcessKeyDown();
}
}
Let me explain my situation. I have a program who reads an external connection and gives me an array of integers (or booleans). Those inputs should feed an object that has some properties (X, Y, Z, for example). So, if a read a value on array, i should write those values in the properties. Is there a way to pass those values by ref (for example) ? Thinking logically , the best way way would be pointers (property X pointing to array[0]), but these aren't very unclear to me.
I can create a way to look for changes in array (but is a very large array, +60000), then update my object. But i think this would be a bad ideia.
Sorry if i wrote any crap, i'm just starting on C#.
Some pseudo code to help.
class obj
{
int X {get; set;}
public obj(ref int x)
{
X = x;
}
}
class main
{
void main()
{
int a;
obj test = new obj(ref a);
}
}
So if: a = 10, obj.X = 10 too.
public class MyClass
{
private int[] backingArray;
public int X
{
get
{
if (backingArray == null)
return -1;
else
return backingArray[0];
}
}
public MyClass(int[] array)
{
if (array.Length > 0)
backingArray = array;
}
}
class Main
{
void Main()
{
int[] array = new int[] { 2 };
MyClass test = new MyClass(array);
array[0] = 6;
Console.WriteLine(test.X);//prints 6
}
}
Of course this only works with reference types (arrays are reference types). If you wanted to do this whole thing with a value type, you'd need to "wrap" it in some reference type. You can use a class such as the following to wrap anything if you don't have anything convenient.
public class Wrapper<T>
{
public T Value { get; set; }
}
It's not possible to use ref in the manor that you've shown in the OP. You wouldn't be able to store the value that was passed by reference. If you could, then you could end up passing some value on the stack and then having the created object that holds the reference living longer than the item on the stack. If that happened you would end up with a reference it a location in memory that no longer holds the variable you intended. This was somewhat of a gotcha in C++ that the designers of C# went out of their way to ensure can't happen (at least not without a lot of work).
*Solved. Thanks for the explanations guys, I didn't fully understand the implications of using a value type in this situation.
I have a struct that I'm using from a static class. However, the behavior is showing unexpected behavior when I print it's internal state at runtime. Here's my struct:
public struct VersionedObject
{
public VersionedObject(object o)
{
m_SelectedVer = 0;
ObjectVersions = new List<object>();
ObjectVersions.Add(o);
}
private int m_SelectedVer;
public int SelectedVersion
{
get
{
return m_SelectedVer;
}
}
public List<object> ObjectVersions;//Clarifying: This is only used to retrieve values, nothing is .Added from outside this struct in my code.
public void AddObject(object m)
{
ObjectVersions.Add(m);
m_SelectedVer = ObjectVersions.Count - 1;
}
}
Test code
VersionedObject vo = new VersionedObject(1);
vo.AddObject(2);//This is the second call to AddObject()
//Expected value of vo.SelectedVerion: 1
//Actual value of vo.SelectedVersion: 1
Now, if you test this code in isolation, i.e., copy it into your project to give it a whirl, it will return the expected result.
The problem; What I'm observing in my production code is this debug output:
objectName, ObjectVersions.Count:2, SelectedVer:0,
Why? From my understanding, and testing, this should be completely impossible under any circumstances.
My random guess is that there is some sort of immutability going on, that for some reason a new struct is being instanced via default constructor, and the ObjectVersions data is being copied over, but the m_SelectedVersion is private and cannot be copied into the new struct?
Does my use of Static classes and methods to manipulate the struct have anything to do with it?
I'm so stumped I'm just inventing wild guesses at this point.
Struct is value type. So most likely you are creating multiple copies of your object in your actual code.
Consider simply changing struct to class as content of your struct is not really good fit for value type (as it is mutable and also contains mutable reference type).
More on "struct is value type":
First check FAQ which have many good answers already.
Value types are passed by value - so if you call function to update such object it will not update original. You can treat them similar to passing integer value to function: i.e. would you expect SomeFunction(42) to be able to change value of 42?
struct MyStruct { public int V;}
void UpdateStruct(MyStruct x)
{
x.V = 42; // updates copy of passed in object, changes will not be visible outside.
}
....
var local = new MyStruct{V = 13}
UpdateStruct(local); // Hope to get local.V == 42
if (local.V == 13) {
// Expected. copy inside UpdateStruct updated,
// but this "local" is untouched.
}
Why is this a struct and not a class? Even better, why are you tracking the size of the backing store (List<T>) rather than letting the List<T> track that for you. Since that underlying backing store is public, it can be manipulated without your struct's knowledge. I suspect something in your production code is adding to the backing store without going through your struct.
If it were me, I'd set it up something like this, though I'd make it a class...but that's almost certainly a breaking change:
public struct VersionedObject
{
public VersionedObject()
{
this.ObjectVersions = new List<object>() ;
return ;
}
public VersionedObject(object o) : this()
{
ObjectVersions.Add(o);
return ;
}
public VersionedObject( params object[] o ) : this()
{
ObjectVersions.AddRange( o ) ;
return ;
}
public int SelectedVersion
{
get
{
int value = this.ObjectVersions.Count - 1 ;
return value ;
}
}
public List<object> ObjectVersions ;
public void AddObject(object m)
{
ObjectVersions.Add(m);
return ;
}
}
You'll note that this has the same semantics as your struct, but the SelectedVersion property now reflects what's actually in the backing store.
Assuming I have a struct:
struct Vector
{
public int X, Y;
// ...
// some other stuff
}
and a class:
class Map
{
public Vector this[int i]
{
get
{
return elements[i];
}
set
{
elements[i] = value;
}
}
private Vector[] elements
// ...
// some other stuff
}
I want to be able to do something like: map[index].X = 0; but I can't, because the return value is not a variable.
How do I do this, if at all possible?
You should avoid mutable structs.
If you want your type to be mutable use a class instead.
class Vector
{
public int X { get; set; } // Use public properties instead of public fields!
public int Y { get; set; }
// ...
// some other stuff
}
If you want to use a struct, make it immutable:
struct Vector
{
private readonly int x; // Immutable types should have readonly fields.
private readonly int y;
public int X { get { return x; }} // No setter.
public int Y { get { return y; }}
// ...
// some other stuff
}
The compiler prevents you from doing this because the indexer returns a copy of an object not a reference (struct is passed by value). The indexer returns a copy, you modify this copy and you simply don't see any result. The compiler helps you avoid this situation.
If you want to handle such situation you should use class instead or change the way you deal with Vector. You shouldn't modify it's value but initialize it's values in constructor, more on this topic: Why are mutable structs “evil”?.
define Vector as class,
or
store value in a temporary variable
var v = map[index];
v.X = 0;
map[index] = v;
or
add function to change
map[index] = map[index].Offset()
or
let the [] operator return a setter class
class Setter { Vector[] Data; int Index; public double X { get { return Data[Index]; } set { Data[Index] = new Vector(value, Data[Index].Y); }}}
public Setter this[int i]
{
get
{
return new Setter() { Data = elements, Index= i };
}
}
Although generic classes work pretty well for many purposes, they do not provide any reasonable way to access structs by reference. This is unfortunate since in many cases a collection of structs would offer better performance (both reduced memory footprint and improved cache locality) and clearer semantics than a collection of class objects. When using arrays of structs, one can use a statement like ArrayOfRectangle[5].Width += 3; with very clear effect: it will update field X of ArrayOfRectangle[5] but it will not affect field X of any other storage location of type Rectangle. The only things one needs to know to be certain of that are that ArrayOfRectangle is a Rectangle[], and Rectangle is a struct with a public int field X. If Rectangle were a class, and the instance held in ArrayOfRectangle[5] had ever been exposed to the outside world, could be difficult or impossible to determine whether the instance referred to by ArrayOfRectangle[5] was also held by some other code which was expecting that field X of its instance wouldn't change. Such problems are avoided when using structures.
Given the way .net's collections are implemented, the best one can do is usually to make a copy of a struct, modify it, and store it back. Doing that is somewhat icky, but for structs that aren't too big, the improved memory footprint and cache locality achieved by using value types may outweigh the extra code to explicitly copy objects from and to the data structures. It will almost certainly be a major win compared with using immutable class types.
Incidentally, what I'd like to see would be for collections to expose methods like:
OperateOnElement<paramType>(int index, ref T element, ref paramType param, ActionByRef<T,paramType> proc) which would call proc with the appropriate element of the collection along with the passed-in parameter. Such routines could in many cases be called without having to create closures; if such a pattern were standardized, compilers could even use it to auto-generate field-update code nicely.