In C#, is there a way to keep a reference as a member variable in an object (like an object pointer in C++), not just as a parameter?
EDIT: How can I make a pointer or reference to an object as a member variable?
No. Don't forget that the argument could reference a local variable which is out of scope by the time you use the object later on. A couple of options:
Use a mutable wrapper type
Use a delegate which captures the variable instead
Redesign your code to not require this in the first place
It's hard to know which is most suitable without knowing more about what you're trying to achieve, but ref is a dead-end.
If you mean ref the argument passing convention, then no, you cannot store this. From the first note on MSDN:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same...
Edit: based on your updated question, C# has different nomenclature about pointers and references. A pointer in C# is an unsafe construct used to somewhat directly reference the memory location of an object. I say somewhat because the memory location can change based on garbage collection (unless you fix it in memory).
References in C# are the default way reference types are passed and stored. They are akin to pointers in other languages, but not quite the same. However, the by-reference argument passing convention allows you to directly change what an object refers to.
If your objective is to keep a mutable reference to a non-reference type local variable, you'll have to encapsulate the local variable in a reference type (like a class). If you could give some sample code, we can give some specific examples.
Yes if it is a reference-type instance. And then it is the only way to store it in another class:
class Bar { }
class Foo
{
private Bar b; // b is a reference to a Bar
}
No if it's about a value-type, or a reference to a reference.
You would see simple object-references everywhere that C++ uses pointers, like in building Trees or Linked-Lists.
class Element { ...; private Element _next; }
For what its worth, you could use an array of size 1 as a reference/pointer. This yields more readable code than creating a new class to wrap a single value type member.
public struct StructWithReferenceMember
{
private int[] intStoredAsReference;
public StructWithReferenceMember(int asValue, int asReference)
: this()
{
IntStoredAsValue = asValue;
intStoredAsReference = new int[] { asReference };
}
public int IntStoredAsValue { get; set; }
public int IntStoredAsReference
{
get { return intStoredAsReference[0]; }
set { intStoredAsReference[0] = value; }
}
}
A similar trick can be used to attempt the highly discouraged practice of using mutable structs.
public class ReferenceProperty<T>
{
private T[] typeReference;
public ReferenceProperty(T value)
{
typeReference = new T[] { value };
}
public T PropertyAsValue
{
get { return typeReference[0]; }
set { typeReference[0] = value; }
}
public T[] PropertyAsReference
{
get { return typeReference; }
}
}
Then use array notation to "dereference" it.
public struct MutableStruct
{
public int member;
public MutableStruct(int value)
{
member = value;
}
}
ReferenceProperty<MutableStruct> referenceToValueType = new ReferenceProperty<MutableStruct>(new MutableStruct(3));
Console.WriteLine("original value: " + referenceToValueType.PropertyAsValue.member.ToString());
//referenceToValueType.PropertyAsValue.member = 4; // compiler error - cannot modify return value because it is not a variable
MutableStruct copyOfStruct = referenceToValueType.PropertyAsReference[0]; // or referenceToValueType.PropertyAsValue
copyOfStruct.member = 4;
Console.WriteLine("original value after modifying copy: " + referenceToValueType.PropertyAsValue.member.ToString());
referenceToValueType.PropertyAsReference[0].member = 5;
Console.WriteLine("original value after modifying reference: " + referenceToValueType.PropertyAsValue.member.ToString());
original value: 3
original value after modifying copy: 3
original value after modifying reference: 5
The way to get the address of a variable is the & operator, similar to C++. Again similarly to C++, you can store the address as a pointer:
class Foo
{
object* _objPtr;
Foo(object obj)
{
unsafe
{
_objPtr = &obj;
}
}
}
Note that any code that uses the address-of operator (&) or pointers must be within a method marked unsafe or within an unsafe code block.
This could be useful if you want to increase performance by not doing array bound-checking for example. The downside (besides safety considerations) is that the assembly must be fully-trusted for it to execute.
As pointed out, in C#, you very rarely actually store pointers, instead you store references so the garbage collector can operate properly. Ensure that you really need pointers in your code before using them!
For more info, see: http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
Related
In C#, is there a way to keep a reference as a member variable in an object (like an object pointer in C++), not just as a parameter?
EDIT: How can I make a pointer or reference to an object as a member variable?
No. Don't forget that the argument could reference a local variable which is out of scope by the time you use the object later on. A couple of options:
Use a mutable wrapper type
Use a delegate which captures the variable instead
Redesign your code to not require this in the first place
It's hard to know which is most suitable without knowing more about what you're trying to achieve, but ref is a dead-end.
If you mean ref the argument passing convention, then no, you cannot store this. From the first note on MSDN:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same...
Edit: based on your updated question, C# has different nomenclature about pointers and references. A pointer in C# is an unsafe construct used to somewhat directly reference the memory location of an object. I say somewhat because the memory location can change based on garbage collection (unless you fix it in memory).
References in C# are the default way reference types are passed and stored. They are akin to pointers in other languages, but not quite the same. However, the by-reference argument passing convention allows you to directly change what an object refers to.
If your objective is to keep a mutable reference to a non-reference type local variable, you'll have to encapsulate the local variable in a reference type (like a class). If you could give some sample code, we can give some specific examples.
Yes if it is a reference-type instance. And then it is the only way to store it in another class:
class Bar { }
class Foo
{
private Bar b; // b is a reference to a Bar
}
No if it's about a value-type, or a reference to a reference.
You would see simple object-references everywhere that C++ uses pointers, like in building Trees or Linked-Lists.
class Element { ...; private Element _next; }
For what its worth, you could use an array of size 1 as a reference/pointer. This yields more readable code than creating a new class to wrap a single value type member.
public struct StructWithReferenceMember
{
private int[] intStoredAsReference;
public StructWithReferenceMember(int asValue, int asReference)
: this()
{
IntStoredAsValue = asValue;
intStoredAsReference = new int[] { asReference };
}
public int IntStoredAsValue { get; set; }
public int IntStoredAsReference
{
get { return intStoredAsReference[0]; }
set { intStoredAsReference[0] = value; }
}
}
A similar trick can be used to attempt the highly discouraged practice of using mutable structs.
public class ReferenceProperty<T>
{
private T[] typeReference;
public ReferenceProperty(T value)
{
typeReference = new T[] { value };
}
public T PropertyAsValue
{
get { return typeReference[0]; }
set { typeReference[0] = value; }
}
public T[] PropertyAsReference
{
get { return typeReference; }
}
}
Then use array notation to "dereference" it.
public struct MutableStruct
{
public int member;
public MutableStruct(int value)
{
member = value;
}
}
ReferenceProperty<MutableStruct> referenceToValueType = new ReferenceProperty<MutableStruct>(new MutableStruct(3));
Console.WriteLine("original value: " + referenceToValueType.PropertyAsValue.member.ToString());
//referenceToValueType.PropertyAsValue.member = 4; // compiler error - cannot modify return value because it is not a variable
MutableStruct copyOfStruct = referenceToValueType.PropertyAsReference[0]; // or referenceToValueType.PropertyAsValue
copyOfStruct.member = 4;
Console.WriteLine("original value after modifying copy: " + referenceToValueType.PropertyAsValue.member.ToString());
referenceToValueType.PropertyAsReference[0].member = 5;
Console.WriteLine("original value after modifying reference: " + referenceToValueType.PropertyAsValue.member.ToString());
original value: 3
original value after modifying copy: 3
original value after modifying reference: 5
The way to get the address of a variable is the & operator, similar to C++. Again similarly to C++, you can store the address as a pointer:
class Foo
{
object* _objPtr;
Foo(object obj)
{
unsafe
{
_objPtr = &obj;
}
}
}
Note that any code that uses the address-of operator (&) or pointers must be within a method marked unsafe or within an unsafe code block.
This could be useful if you want to increase performance by not doing array bound-checking for example. The downside (besides safety considerations) is that the assembly must be fully-trusted for it to execute.
As pointed out, in C#, you very rarely actually store pointers, instead you store references so the garbage collector can operate properly. Ensure that you really need pointers in your code before using them!
For more info, see: http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
I am a bit confused here. With structs, I cannot directly change its fields as the whole struct is of the value type.
But what about classes with value type fields? If I have a public field int X, I can modify it properly. So the only manifestation of value-type nature of its field would be that when passed as an argument, it is a copy?
EDIT: Also
Class A
{
int B=100; //this is a field, so reference type. But it is a value type.
}
The address to content of B is stored on the heap, but is the value of B stored on the stack?
With structs, I cannot directly change its fields as the whole struct is of the value type.
You cannot change fields in situations when C# makes a copy of the struct for you. In other situations, you can modify fields of a struct. Here is a small demonstration of the difference:
struct Foo {
public int A {get;set;}
public void SetA(int a) {
A = a;
}
}
class Bar {
Foo f;
public Foo F {
get{return f;}
set {f = value;}
}
public void SetFooA(int x) {
f.SetA(x);
}
}
public static void Main() {
Bar b = new Bar();
b.F.SetA(123); // b.F makes a copy, so changing A fails
Console.WriteLine("{0}", b.F.A);
b.SetFooA(456); // Inside Bar, f.SetA is called directly, so the change works fine
Console.WriteLine("{0}", b.F.A);
b.F = new Foo { A = 112233 }; // This also works, because the whole F is assigned
Console.WriteLine("{0}", b.F.A);
}
If I have a public field int X, I can modify it properly.
The same rule applies to user-defined structs, as long as you modify the whole of it. You can't modify part of an int, because it is not a composite. Modification of a struct works fine when you assign the whole struct at once. In other words, assigning
b.F = new Foo { A = 112233 };
in my example replaces assigning
B = 100;
in your example.
Demo.
The address to content of B is stored on the heap, but is the value of B stored on the stack?
No. Value type fields of a class are stored on the heap.
Please refer to #Marc Gravell's answer here for more information about this:
Why value-types are stored onto Stacks?
You may also want to read #Eric Lippert's blog post on the subject: https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/
In short value types can be stored on the stack but they are not always stored on the stack.
Struct gives you a copy of the original field because a copy of the struct would be passed. Changing it to class would pass a reference to the class and therefore the field would modify if you were to change it.
Out of curiosity: Is there a way to create a class whose reference to the class instance can never be set to null?
Like haveing only a readonly pointer that can only be set to null by the class itself.
What I have in mind:
I would want to have an easy to read /use object that either exists with data or exists without (shown by an attribute like hasData = false). It is always accessable and should never be null / point to nowhere which as a side effect gets also rid of NullReferenceExceptions for objects that are sometimes supposed to not have a value without the need of checking for null.
This feature does not exists (yet). There is big discussion of non-nullable reference types at Roslyn forum: non-nullable reference types (the one billion $ mistake). But currently you cannot restrict reference type variable from assigning null value.
You can use value type (struct) instead, but it's not stored in heap, passed by value etc.
All other options will not guarantee that someone will not assign null to variable of your reference type. But you still can use something like Null Object pattern to simplify your life (processing objects without data in same way as usual objects).
In such a case, you may want to use a struct instead of a class. Class is a reference type and therefore its default value is null, hence a variable containing an instance can be nulled (assigned null). There is no way to prevent it. On the other hand, struct is a value type and default for struct is an empty struct - i.e. a struct whose members are set to their defaults (0 for an int field, null for a field of a reference type etc.)
Example of a struct
public struct Foo
{
public int Bar;
}
And its usage (notice it is not instantiated but still it is NOT null)
Foo foo;
foo.Bar = 1;
More about structs can be found here on the MSDN sites.
As Anton mentioned, you could use a struct which cannot have a default value of null. But I am thinking you want something more like this:
public class DataObject
{
public static bool HasData
{
get
{
return myObject != null;
}
}
public static DataObject PresistentDataObject
{
get
{
return myObject;
}
}
static DataObject myObject = new DataObject();
}
This code seems like bad practice. And maybe you'd want to resort to something like dependency injection with a singleton which will avoid setting up a state class like this.
Typically, the motivation behind such a question drives the qualities/properties of a solution.
Here, I suppose, the motivation is to avoid runtime exceptions of (faulty) code which tries to access a null reference as if it held an instance.
class Foo<T> {
T data; // might be null or hold an instance...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays(); // might return null...
}
bool DoSomething() {
return data.Value > 5; // might throw an exception...
}
// ... more members...
}
To prevent this type of errors, you could borrow from C#'s cousin language F#.
If the function T GetInstanceOfTInMysteriousWays<T>() by design and contract is permitted to either return an instance or a null value, a better design of that function would be to have it return not T but an Option<T>. Then, the type of Foo.data would not be T but Option<T> and the user code in DoSomething() could not simply access member data.Value. Thus, this common pattern of bugs would be eliminated.
// Improved code from above
class Foo<T> {
Option<T> data; // Option is a struct type and cannot be null...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays();
}
bool DoSomething() {
if (data.IsSome() ) {
return data.TryGetValue().Value > 5;
}
return false;
}
}
Now the only question is, where to find that Option type in C#? There are several github projects creating such a type (google is your friend). You could also consider to link the F# core library and use the Option type defined there, maybe along with a little helper as is shown in this gist snippet.
If your class is named foo, then you would have at least one constructor (possibly more). In that constructor you would assign the variable to false.
public foo(){
hasData = false;
}
As #Anton points out, this only works if the variable is instansiated.
foo f = new foo();
it would still be null if you assigned it as null:
foo f = null;
I'm not sure, I understand the question correctly or not. Let me add
some points here:
Hope that you misunderstand the term Instance, If you create an instance of the class then it will not be null, Let myClass be a class that you have created already. You are not creating any instance of the class by using myClass myClassObject. The myClassObject will became an instance of the class only when an instance of the class is assigned to it, Until then it is null which means not existing.
As others have mentioned, you'd need a struct for that.
However, we can tackle this from a different angle (in a class):
Since the variable can point to null, let's define the variable in a way that it can't be set to null:
private Class1 _c = new Class1();
public Class1 c { get { return _c; } set { if (value != null) _c = value; } }
so c will not be set to null.
A struct per your requirements:
struct Struct1
{
public bool hasData { get { return Data != null; } }
public Class1 Data;
}
I am creating a simple text-game. My Character struct keeps resetting it Can value. What am I doing wrong and how do I fix it? Here is the code:
namespace MyNamespace
{
struct Character
{
public float Can;
//...
}
class MainClass
{
public static void Move (Character a)
{
bool cal = true;
while (cal)
{
Thread.Sleep(500);
if(a.Can <= 100)
{
a.Can += 1;
}
else
{
cal = false;
}
}
}
}
//...
}
A struct is a value type. When you pass it to a method or assign it to another variable, data are copied. You will then operate on a copy.
Consider your method call Dinlen (oyuncu);. It copies the Karakter oyuncu, and then changes the field Can of the copy.
Consider using reference types (class) instead. If you use a struct, consider making it an immutable type. Read the thread Why are mutable structs evil?
If you want to pass a struct to a method for the purpose of having that method modify it, the method must use a ref qualifier on the parameter. If you pass a struct to a method without a ref parameter, there is no way that the method can modify any fields of that struct.
Note that some people may suggest replacing the struct with a class so that one won't have to use the ref qualifier. That is a dangerous notion, since every method receiving a reference to a mutable class object will be free to cause the object to be mutated at any time thereafter. There's no clean way to pass a reference to a mutable class object without allowing the recipient to mutate it, nor is there any way to be certain that code which is given a class-object reference won't persist it and use it to modify the object at any arbitrary future time. Structures don't have either of these problems.
If an object holds a value-type field e.g. MyBounds of type Drawing.Rectangle, and I call Foo(MyBounds) I can be assured that there is no possibility that Foo will change MyBounds. Further, if I call Bar(ref MyBounds) I can expect that Bar might change MyBounds, but all changes will be complete before the method returns. If Rectangle had been a mutable class type, then without examining Foo and Bar I would have no way of knowing whether the properties of MyBounds might be changed at any arbitrary time in the future.
Someone who doesn't understand that structs are different from classes may be confused by the way structs behave, but all structs with exposed public fields behave the same way, so if one understands how one such struct works, one will understand them all. There is one evil aspect of structures, which is that instance methods and properties defined on a struct will receive this as a ref parameter, but if one attempts to do something like:
readonly System.Drawing.Rectangle myRect = whatever;
...
myRect.Offset(4,2);
the system will recognize that myRect cannot be passed as a ref parameter (since it's read-only) and will, without any diagnostic, change the code to:
readonly System.Drawing.Rectangle myRect = whatever;
...
System.Drawing.Rectangle temp = myRect;
temp.Offset(4,2);
What is evil there, however, is not the fact that Rectangle is mutable, but rather the fact that the compiler assumes the above code substitution is legitimate when calling any and all value-type methods. Unless or until Microsoft gets around to adding an attribute to indicate that calling a particular method on a read-only structure should result in an error rather than performing such substitution, the only safe way to code struct methods that operate on a structure "in-place" would be to use a format like: static void Offset(ref Rectangle it, int x, int y);, in which case Rectangle.Offset(ref myRect, 4, 2); would fail as it should.
I believe the problem is you are passing the struct as a variable into your first method, but struct's are value types - i.e. they are copied, not passed by reference.
Changing your struct to class will have the behaviour you require.
P.S. Is there a reason you chose a struct? They are normally used for more advanced scenarios, where the developer knows more about the benefits and flaws of using this type.
When you are passing struct instance into method, a copy of struct is created (it is passed by value). Any changes to struct inside method does not affect original struct which you passed.
Solutions? Use class instead of struct. Instances of classes passed by reference. Well you can pass structs by reference, but why would you trying to use structs like classes? Use classes instead.
class Karakter
{
public string Isim { get; set; }
public float Can { get; set; }
public int Seviye { get; set; }
public int Exp { get; set; }
public float Guc { get; set; }
public string Irk { get; set; }
public int vExp { get; set; }
public override string ToString()
{
return String.Format("Adınız:{0}\nIrkınız:{1}\nCan:{2}\nGuc:{3}",
Isim, Irk, Can, Guc);
}
}
BTW I think it will be useful for you to read about Value and Reference Types in .NET
You might want to consider using a class instead of a struct.
As said, a struct is a value type and passed by copy. You can pass it by ref like this:
public static void Move (ref Character a)
{
...
}
and call it like this:
var a = new Character();
MainClass.Move(ref a);
If you must pass a value type to a method, but for some reason, it must be passed as a reference type, is it faster to:
Pass it as an object
Pass is as a ValueType
Pass it as a generic wrapper
I put some example code below to demonstrate exactly what I mean:.
public class Program
{
public void Main()
{
var client = new IncrementedValueGetter();
int i = 8675309;
var byObject = client.IncrementObject(i);
var byValueType = client.IncrementValueType(i);
var byWrapper = client.IncrementWrapped(new ValueWrapper<int>(i));
}
}
public class IncrementedValueGetter
{
public int IncrementObject(object boxedValue)
{
return ((int)boxedValue) + 1;
}
public int IncrementValueType(ValueType boxedValueType)
{
return ((int) boxedValueType) + 1;
}
public int IncrementWrapped(ValueWrapper<int> valueWrapper)
{
return valueWrapper.Value + 1;
}
}
public class ValueWrapper<T>
where T: struct
{
private readonly T _value;
public ValueWrapper(T value)
{
_value = value;
}
public T Value
{
get { return _value; }
}
}
The first two are actually equivalent, and just generate the standard box IL. The third one requires the construction of your wrapper class, which is likely more expensive than the box call.
The performance is probably comparable for all three since ultimately a value type must be represented in a reference type which means boxing at some point. But you can make things worse with unnecessary overhead and wrapping.
The important thing to realize about boxing is that it is not inherently expensive, it is only relatively expensive in context of something specific like boxing and unboxing in a tight loop. Try to focus on why you cannot use the the value type itself and why you need to use a reference type and let that guide your design. How would you like to access the value type from the reference type. Will the reference type hold other reference types? And so on.
Above all, if you're really concerned, just code it up and measure it. And keep measuring it in the context of your application, if it is performance critical, and you application evolves.