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.
Related
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...
}
}
I have a value (struct instance) that was cast to object for generic handling. I need to make a copy of the value. I cannot do this explicitly because I just have its Type and don't know what it is in compile time.
By default I get a copy of reference: var copy = objectOfMyStruct;. I thought about making an explicit shallow copy by MemberwiseClone() but I cannot do this because it's protected method and I cannot modify MyStruct.
Convert.ChangeType(objectOfMyStruct, typeOfMyStruct) doesn't help because conversion (actually no conversion) happens inside and it returns Object again.
How could I do this?
EDIT:
I need to make a copy to preserve original value and just deserialized one to pass to OnChangeHandler. Simplified implementation is:
var oldValue = type.GetValue(reference);
var newValue = oldValue; // something better is needed here
Deserialize(type, stream, ref newValue);
OnChange(oldValue, newValue);
type.SetValue(reference, newValue);
Copy is made because only delta (changes) are sent so should be applied to the original value.
EDIT 2:
This implementation works fine for primitive types, so despite int is boxed too I'm copying it instead of copying reference to it. I just don't understand this.
Here is an example of what is needed.
This example, which you can test in LINQPad should make a clone of the struct without casting it back to its unboxed type, so that when it is mutated by a call through the implemented interface, only the original is mutated. The question is thus; how do I write that Clone method?
void Main()
{
object original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = Clone(original);
((IDummy)original).Mutate(); // will modify the boxed struct in-place
original.Dump();
// should output different if Clone did its job
clone.Dump();
}
static object Clone(object input)
{
return input;
}
public interface IDummy
{
void Mutate();
}
public struct Dummy : IDummy
{
public int Property { get; set; }
public string Field;
public void Mutate()
{
Property = 77;
Field = "Mutated";
}
}
I assume that you not only want to make a copy, but also be able to actually use that copy.
And in order to use it, you need to cast (unbox) it to the appropriate type, which effectively makes a copy. In fact, even putting the value into the box already resulted in a copy.
So, if (for example) you know that these objects are either ints or floats, you could do:
if (obj is int)
{
int i = (int) obj;
// do something with the copy in i
}
else if (obj is float)
{
float f = (float) obj;
// do something with the copy in f
}
If you have a large number of types to evaluate, you can use a switch statement or even a Dictionary<Type,Action<object>>.
If you need to deal with types that you don't know about at compile time (some type added dynamically thorugh some kind of plugin mechanism) than this won't be possible, but then again, it would also not be possible to do anything with the object (unless through an interface).
UPDATE:
Now that you changed your question, here's a better answer: you do no need to make a copy, it has been made for you by boxing the struct.
Example:
int i = 42;
// make a copy on the heap
object obj = i;
// modify the original
i = i + 1;
// copy is not modified
Debug.Assert((int)obj == 42);
Obviously, I'm using int here for convenience, but it is true for every struct. If the struct implements an interface, you can cast the object to that interface (that won't make a second copy) and use it. It will not modify the orginal value, because it is operating on the copy in the box.
UPDATE 2:
Just to be very explicit: this works for every struct. For example:
interface IIncrementor
{
void Increment();
}
struct MyStruct : IIncrementor
{
public int i;
public void Increment()
{
this.i = this.i + 1;
}
public override string ToString()
{
return i.ToString();
}
}
// in some method:
MyStruct ms = new MyStruct();
ms.i = 42;
Console.Writeline(ms); // 42
object obj = ms;
IIncrementable ii = (IIncrementable) obj;
ii.Increment();
Console.Writeline(ms); // still 42
Console.Writeline(ii); // 43
One more UPDATE:
instead of
object original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = Clone(original);
write
Dummy original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = original;
and you'll be fine.
Thanks for the LINQPad example, it greatly clarified your question and it gave me a starting point for coming up with a solution.
This is a very brute-force solution, but it might serve your purpose, until somebody comes up with a more elegant answer:
static object Clone(object input)
{
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(input));
try
{
Marshal.StructureToPtr(input, p, false);
return Marshal.PtrToStructure(p, input.GetType());
}
finally
{
Marshal.FreeHGlobal(p);
}
}
This is how it works:
It allocates unmanaged memory large enough to hold your struct.
StructureToPtr unboxes your input and copies it into unmanaged memory:
If structure is a value type, it can be boxed or unboxed. If it is boxed, it is unboxed before copying.
PtrToStructure creates a new structure, boxes it and returns it:
You can pass a value type to this overload method. In this case, the returned object is a boxed instance.
The unmanaged memory is freed.
Here's another answer:
static object Clone(object input) =>
typeof(object)
.GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(input, null);
It uses the Object.MemberwiseClone method. This method is protected, which is why I have to call it via reflection.
This approach works fine with enums, and with structs that have [StructLayout(LayoutKind.Auto)].
If the list of types to handle this cloning for is controlled, that is, you know which types you need to handle this for, then I would simply create a dictionary that contains functions that knows how to handle each particular type.
Here's a LINQPad example:
void Main()
{
_CloneMapping[typeof(Dummy)] = (object obj) =>
{
Dummy d = (Dummy)obj;
return new Dummy { Field = d.Field, Property = d.Property };
};
object original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = Clone(original);
((IDummy)original).Mutate(); // will modify the boxed struct in-place
original.Dump();
// should output different if Clone did its job
clone.Dump();
}
static readonly Dictionary<Type, Func<object, object>> _CloneMapping = new Dictionary<Type, Func<object, object>>();
static object Clone(object input)
{
if (input == null)
return null;
var cloneable = input as ICloneable;
if (cloneable != null)
return cloneable.Clone();
Func<object, object> cloner;
if (_CloneMapping.TryGetValue(input.GetType(), out cloner))
return cloner(input);
throw new NotSupportedException();
}
public interface IDummy
{
void Mutate();
}
public struct Dummy : IDummy
{
public int Property { get; set; }
public string Field;
public void Mutate()
{
Property = 77;
Field = "Mutated";
}
}
This will output:
The background is that in NHibernate mapping, as the collection field is declared in base class and dynamically proxied at runtime.
As there is some proxy class which need refer to the collection field during my coding, however, as NHiberate reassign the field with its own collection instance, the proxy loses the reference.
Tried use ref to "track" the reference, but failed with weired outcome.
Can some experter help explain about the root cause with both C# ref keyword and NHiberate collection proxy if any.
Thanks.
class Program
{
static void Main(string[] args)
{
var v = new D();
}
}
class A
{
}
class B : A
{
}
class C
{
public A a = new A();
public Proxy p;
public C()
{
p = new Proxy(ref a);
p.Out();
}
}
class D : C
{
public D()
{
a = new B();
Console.WriteLine(a.GetType().Name);
p.Out();
}
}
class Proxy
{
public A a;
public Proxy(ref A a)
{
this.a = a;
}
public void Out()
{
Console.WriteLine(a.GetType().Name);
}
}
Expected output:
A
B
B
Actual output:
A
B
A
Tried use ref to "track" the reference, but failed with weired outcome.
There's nothing weird about this outcome - you just don't understand ref sufficiently. ref only affects the parameter it's declared on.
So on this line:
this.a = a;
you're just copying the current value of the a parameter into the a field. Any later changes to the value of the parameter within the constructor (not that there are any) will not be reflected in the field - and any changes to the variable which was used as the argument again won't be reflected in the field.
So changing the a field within the C class (it would really have helped if you'd used different names for the fields and parameters) doesn't change the value within the Proxy instance's a field at all.
Note that this has nothing to do with NHibernate, either - it's just the standard C# behaviour.
I'm making a library which will perform operations to read a processes memory, and get information from said process.
The problem I have is that to call the functions, I have to pass a lot of the variables every time, even if their values haven't changed.
For instance, ReadProcessMemory requires me to pass:
Process Handle
Memory Address
Main Module Base Address
Amount of bytes to read
The only thing that will be changing for each read is the Memory Address, so I don't really need to pass the rest of the variables every time I call the function (I actually have 3 functions which can be reduced in this way, and may have more shortly).
Could anyone give me a brief explanation as to how I should go about this? Will the variables exist at runtime so I can just call the function and use them directly from the DLL file?
You can use named parameters when calling methods with optional parameters.
public void MyMethod(string s = null, int i = 0, MyType t = null)
{
/* body */
}
Call it like so:
MyMethod(i: 10, t: new MyType());
MyMethod("abc");
MyMethod("abc", t: new MyType());
Alternatively you could use overloads:
public void MyMethod(string s)
{
MyMethod(s, 0, null);
}
public void MyMethod(int i)
{
MyMethod(null, i, null);
}
public void MyMethod(MyType t)
{
MyMethod(null, 0, t);
}
public void MyMethod(string s = null, int i = 0, MyType t = null)
{
/* body */
}
Yet another option is to use a parameters class like so:
public class MyParametersClass
{
public string s { get; set; }
public int i { get; set; }
public MyType t { get;set; }
public MyParametersClass()
{
// set defaults
s = null;
i = 0;
MyType = null;
}
}
public void MyMethod(MyParametersClass c)
{
/* body */
}
Calling like so:
MyMethod(new MyParametersClass
{
i = 25,
t = new MyType()
});
Using the parameters class is likely your preferred approach. The parameters class can be carried around as you process whatever you're processing. :) Any changes made to it will not be lost...
var parameters = new MyParametersClass();
MyMethod(parameters);
parameters.i = 26;
MyMethod(parameters);
One approach is to convert method call into object and have arguments cached in such object. Called refactoring to "method object".
Approximate sample (Tx - are some types):
int My.ReadProcessMemory(T1 a1, T2 a2, T3 variable)
{...}
class ReadProcessMemory
{
T1 a1;
T2 a2;
public ReadProcessMemory(T1 a1, T2 a2)
{
this.a1 = a1;
this.a2 = a2;
}
public int Run(T3 variable)
{
return My.ReadProcessMemory(a1, a2, variable);
}
}
Write a wrapper class for this ... set up the variable as properties or parms for the "new thing(...)" then subsequent calls are thing.Read(MemoryAddress)
In addition to using named parameters you will need to store the values that don't change in your library somehow.
If these are just runtime variables then you can just use class variables (if your library is a class) or static variables (if not). This does however, mean that your library is storing the state of the system and must verify that the state is still valid on every call.
Requiring the values to be passed in each call is actually a much cleaner interface and forces the users of your library to work in a consistent manner.
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!