C#: weird ref in constructor to behave like "virtual field" - c#

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.

Related

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.

C# Get subclass attribute value

I'm trying to make this:
class A {
//attibutes
}
class B : A {
public int classBAttribute = 5;
// other attributes and methods
}
My question is this if I have an instance of A class how can i get the instance of the B class or access his attributes?
B b = new B();
Application.Add(b);
//other form
A a = Application.GetA();
B b = getBFromA(a);// ??? Note: B b = a as B; does't work i tried
You cannot do this -- there is no magical way to create derived objects from base objects in general.
To enable such a scheme class B would need to define a constructor that accepts an A argument:
public B(A a)
{
// do whatever makes sense to create a B from an A
}
which you can then use as
var b = new B(a);
Of course after this a and b will be completely different objects; changing one will not affect the other.
You should also get the terminology right in order to avoid confusion: classBAttribute is not an attribute, it is a field.
My question is this if I have an instance of A class how can i get the
instance of the B class or access his attributes?
How would your program know an instance of A is actually of type B?
An instance of B could be used as A (as B is a specialization of A), but the opposite is not possible.
Maybe I don't fully understand the question or the answers, but...
Casting an A to a B should work (as long as the A is actually (also) a B).
A a = Application.GetA();
if(a is B)
{
B b = (B)a;
DoSomething(b.classBAttribute);
}
else
{
// TODO: Some fallback strategy or exception (?)
}

Avoiding passing unchanged variables into a library

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.

Can't pass variables of base types as out parameters?

Just noticed this doesn't work:
var dict = new Dictionary<int, XElement>();
XContainer element;
//...
if (dict.TryGetValue(idx, out element)) { //...
Then I tried this:
class A { }
class B : A { }
class Program {
static void Main() {
A a;
a = Ret(); // no error, ok
Ref(ref a); // compiler error, ok...
Out(out a); // compiler error, lolwut?!
}
static B Ret() { return null; }
static void Ref(ref B b) { }
static void Out(out B b) { b = null; }
}
Why do I get a compiler error in the last call?
Edit: Ok, so as I understand from the answers 'out' is 'ref' in disguise, so it can be shared and changed by other functions or threads. But really, isn't 'out' supposed to be a way to return multiple values from a function? Because if so, it doesn't seem to be good at it. If sharing creates problems, then don't share. Just create a hidden variable at the start of the function, and work with it. I mean:
static void Out(out B b) {
B bHidden; // compiler generated;
// all references to b are replaced with bHidden;
b = bHidden;
}
Is there any reason it can't be done this way? It seems safe to me now...
as I understand from the answers 'out' is 'ref' in disguise, so it can be shared and changed by other functions or threads. But really, isn't 'out' supposed to be a way to return multiple values from a function? Because if so, it doesn't seem to be good at it. If sharing creates problems, then don't share. Just create a hidden variable at the start of the function, and work with it. I mean:
static void Out(out B b)
{
B bHidden; // compiler generated;
// all references to b are replaced with bHidden;
b = bHidden;
}
Is there any reason it can't be done this way? It seems safe to me now...
Such a system is called a "copy out" system, for obvious reasons. It could be done that way, but doing so creates interesting problems of its own. For example:
void M()
{
int b = 1;
try
{
N(out b);
}
catch (FooException)
{
Console.WriteLine(b);
}
}
void N(out int c)
{
c = 123;
P();
c = 456;
}
void P()
{
throw new FooException();
}
What is the output of the program? What should it be?
Next problem: Do you want out's behaviour to be consistent or inconsistent with ref? If you want it to be inconsistent, then congratulations, you just added a highly confusing inconsistency to the language. If you want it to be consistent then you need to make ref use "copy in copy out" semantics, which introduces a number of problems of its own, both in terms of performance and in terms of correctness.
I could go on all day enumerating the differences between reference semantics and copy semantics, but I won't. The system we've got is the system we've got, so learn to work with it.
And besides, if you want to return more than one value from a method, don't use an out parameter. That might have been the smart thing to do in 2001, but it is 2012 now and we have more tools at your disposal. If you want to return two values:
return a tuple
refactor the code into two methods that each return one value
if the two values are a value type and a bool, return a nullable value type.
Eric Lippert has written about this: http://blogs.msdn.com/b/ericlippert/archive/2009/09/21/why-do-ref-and-out-parameters-not-allow-type-variation.aspx
Modifying your example:
class A { }
class B : A { public int x; }
class Program {
static void Main() {
A a;
a = Ret();
Out(out a, () => a = new A());
}
static B Ret() { return null; }
static void Ref(ref B b) { }
static void Out(out B b, Action callback) {
b = new B();
callback();
b.x = 3; // cannot possibly work, b is an a again!
}
}
C# specification indicates types must be exact match:
17.5.1.3 Output parameters
When a formal parameter is an output parameter, the corresponding argument in a method invocation shall consist of the keyword out followed by a variable-reference (ยง 12.3.3.27) of the same type as the formal parameter.
If it was allowed, you could do this:
class A { }
class B : A { public void BOnlyMethod() { } }
class C : A { }
public class Violations
{
private A a;
public void DoIt()
{
Violate(out this.a);
}
void Violate(out B b)
{
b = new B();
InnocentModification();
// what we think is B, is now C in fact, yet we still can do this:
b.BOnlyMethod();
// which is bound to fail, as BOnlyMethod is not present on type C
}
void InnocentModification()
{
this.a = new C();
}
}
If such restriction wasn't present, violations of type system like the one above would be way too easy to achieve. And I suppose you don't want this kind of "possibilities" in your language.
The question is basically: Aren't a = Ret() and Out(out a) supposed to be logically equivalent? If so, why one works and the other doesn't?
If I understand correctly, CLR doesn't actually have out and instead uses ref, which means that behind the scenes Out(out a) is implemented as Out(ref a), which fails for obvious reasons.

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