C# - Detect when an object reference was changed - c#

Supose that:
object x;
void GiveMeARef(ref object obj)
{
x = obj;
}
So I want that X change this value when Y is changed. For instance:
Y = new MyObject;
GiveMeARef(Y); //So x == Y;
Y = new OtherObject; // I want that X continues equals to Y, but it doesn't:\
Anyone knows how I can do this in C# if it is possible?
Sorry about my poor english
Thanks in advance

This code smells of a larger problem ... but why not just do:
var y = new MyObject();
GiveMeARef(ref y);
var z = new MyObject();
No need to reuse y.

without getting into low-level debugging techniques (like what Visual Studio uses when it's debugging your code), I don't think there's a straightforward way to do this.
What you're looking for is an alias, not a reference, and to my knowledge, that isn't supported by the CLR.
You might be able to do it by writing unsafe code, but I would suspect that there might be some significant side-effects and complications from doing this.

It really isn't clear to me what you are trying to do, but I'd be using a property:
private SomeType y;
public SomeType Y {
get { return y;}
set {
if(y!=value) {
y = value;
// run any "things to do when Y changes" code
OnYChanged();
}
}
}
public event EventHandler YChanged;
protected virtual void OnYChanged() {
EventHandler handler = YChanged;
if(handler!=null) handler(this, EventArgs.Empty);
}
Now you can watch for changes to obj.Y in 3 different ways:
in the Y setter
via the YChanged event
by subclassing and overriding OnYChanged

It seems like you want X to be a pointer to Y. Pointers aren't supported directly in C# (only in unsafe code) but you can achieve this properly by a litte hack with closures/lambda-expressions.
Try converting this VB-tip to C# (Pointer<T>-Structure)

There is no way to do what you are attempting (directly).
The closest thing I can think of would be to have Y be encapsulated inside of some other class, and have GiveMeARef() take the class instance instead of Y directly. This would look something like:
myClass.Y = new MyObject();
GiveMeARef(ref myClass);
myClass.Y = new MyObject();
Then you'd be able to still have the internal reference find Y - even though it wasn't staying exactly the same.

The easiest solution is to assign values to Y using a property, and update X in the setter function:
private MyObject m_Y = new MyObject();
public MyObject Y
{
get { return m_Y; }
set
{
m_Y = value;
X = value; // Here ...
}
}
Another solution is creating a new class, MyObjectWrapper, and deal with it instead ...
Another thing, there isn't any point of the 'ref' in GiveMeARef(ref object obj) .. it's already passed by reference.

This would also achieve the result, keeping the assignment at the time of the "new" operation, assuming that in your example you are using many different news and want X to be updated each time.
private static object x;
private static object CreateNew(Type t) {
object temp;
temp = System.Activator.CreateInstance(t);
x = temp;
return temp;
}
static void Main(string[] args) {
object o = CreateNew(typeof(int));
o = CreateNew(typeof(long));
}
Where you use reflection to create the instance of the object and assign it to the keeper variable at the same time. It very much depends on what the nature of the problem is as to which is the appropriate solution.

Related

Beginner: Is there an elegant way to update all copies of an instance?

The following code doesn't update the copy of a inside the array.
int a = null;
int[] numbers = new int[1];
numbers[0] = a;
a = 5; // 5
Console.WriteLine(numbers[0]); // null
Got a programming task requiring to set-up a structure of locations linked by portals between them which isn't possible by just listing the required connections. I'll get references to null that stay null even if I fill an entity later in the code.
Looking for keywords or techniques which might solve my issue.
You could have reference types instead of value types inside array, therefore updating the value of the inner object will also affect the array.
var tab = new MyClass[1];
var obj = new MyClass(5);
tab[0] = obj;
Console.WriteLine(tab[0].Value); // 5
tab[0].Value = 10;
Console.WriteLine(tab[0].Value); // 10
obj.Value = 15;
Console.WriteLine(tab[0].Value); // 15
public class MyClass
{
public MyClass(int value)
{
Value = value;
}
public int Value { get; set; }
}
integers is a value type, as such the actual value is copied. So there is never any 'instance' in your example code, only copies of the value.
You should probably wrap your value in a class, since classes are a reference type to get your desired behavior. This might be useful when you need to share some mutable between multiple components. You can also add an event that is raised whenever the value is changed to let any component that needs the value know that it might need to update something. For example:
public class MyChangeable<T>
{
private T value;
public MyChangeable(T value) => this.value = value;
public T Value
{
get => value;
set
{
this.value = value;
OnChanged(this, value);
}
}
public event EventHandler<T> OnChanged;
}
There is also ref return and ref locals that could do something like your example, but this is mostly intended to get better performance by avoiding copies of large structs, it is not as useful if you want to share values between components.
Arrays are reference types
var a = new int[1];
var numbers = new [] { a };
a[0] = 5;
Console.WriteLine(numbers[0][0]);
You just have to remember that you're one level deeper than you wanted to be/you need to stick a [0] on everything you wouldn't have stuck it on before. It's a bit of a hack, and I'd probably make a class for it like other answers recommend, but stuffing a value type in an array of size 1 can be a useful technique to quickly get reference type behavior out of a value type
ref locals may help you in your task, even if they have strict limitations due to the lifetime of the involved objects, so they could be not applicable as a general solution.
A small example based on your question can be as follows:
int[] array = new int[1];
ref int elem = ref array[0];
elem = 5;
Console.WriteLine(array[0]); // 5
This works not only with value types (including nullable types) but also with reference types.

How to extract a static value from a type parameter

The code looks like this.
public class One<T> where T : Two {
public static int Y;
static One() {
// Y is to be initialised with the Z value from T
// this code does not compile
// Y = T.Z;
}
public int X { get { return Y; } }
}
public class Two {
public static int Z = 42;
}
public class Three {
public void Main() {
One<Two> a = new One<Two>();
Console.WriteLine("X = {0}", a.X); // should say 42
}
}
The idea is very simple: initialise the static value in a class from another static value in another class passed as a type parameter. There is nothing 'unsafe' about this, but the natural way to do it does not compile (see code).
I've searched SO and found a few near misses, but nothing that hits the spot. I've tried a few things including reflection, but to no avail. Any solution or even hints much appreciated.
Flydog's given you something you could use; I just wanted to make a quick note about my/jimi/enigmativity's comments:
It feel like you're hoping to subclass Two at some point and change out the Z; you reason that if your new class Three, which has a static Z of 43 and derives from Two, is used in combination with One then you'll end up with an .X that is 43. The problem comes in that static things cannot be overridden; they're resolved at compile time and they can look like overriding is at play in certain circumstances, but it's actually overloading or hiding and the compiler is picking something with a particular name in a defined order out of the inheritance tree
Because static things don't inherit (and arguably don't need to because they are hence always known to you, the developer, at compile time) there isn't the expectation that one day someone will subclass your code and write :
One<Four> a = new One<Four>();
And your code will need to pick up whatever they set Z to and use it. You know your Zs and can use them appropriately at compile tine and they know their Zs and should use them appropriately. But I understood where you were going with the T.Z thing..
It almost looks like it should work. Then you start typing T.Z and realize that your gut is agreeing with the compiler. T is a type parameter, it isn't a full fledged type-y thing.
Anyways, this works:
static One()
{
// Y is to be initialised with the Z value from T
var typeT = typeof(T);
var zFieldInfo = typeT.GetField("Z");
Y = (int) zFieldInfo.GetValue(null);
}
Yeah, it uses reflection, but it's only ever going to be run once.

Anonymous object ~ object does not contain a definition for property

The following code will not compile if I include f1().
However, I see both X & Y in intellisense with their values at the call to calculationXY() in the call from f2().
The f1() compile error is: object does not contain a definition or x {or for y for that matter and the .x is red underlined.
private object calculateXY(int id) {
// bla bla bla
return (new { x = calX, y = calY });
}
/*
f1() {
var p = calculateXY(10);
p.x + 1;
}
*/
f2() {
var p = calculateXY(10);
//p.x + 1;
}
I'm added this just to complete the answer.
In the whole solution this class is only instantiated twice. And it is small so I think I'm okay.
public class plotPoint {
public plotPoint (int x, int y){
this.x = x;
this.y = y;
}
public int x { get; set; }
public int y { get; set; }
}
and
private plotPoint calculateXY(int id) {
//bla bla bla
return (new plotPoint(_pointX, _pointY));
}
Although I don't exactly love the name.
I guess I've been doing to much javascript lately. JS would have a problem with what I was hoping to get away with. Oh well.
And so we see the death of yet another pointlessly crazy use of a global variable.
Thanks for everyone's input.
calculateXY returns an object .. which has no x or y properties; you
can return a dynamic instead, or use reflection to read x and y –
KMoussa
and
As #KMoussa states, you're returning an object. Best bet is to return
dynamic, but if you're returning an object, you should just return a
proper class or struct. – TyCobb
Thanks guys.
I'd recommend writing an IntPoint class:
public class IntPoint { int X; int Y; }
And return that. Make sure you declare the method's return type as IntPoint as well, so you can easily use the return value without any nonsense:
private IntPoint CalculateXY(int id) {
// bla bla bla
return new IntPoint { X = calX, Y = calY };
}
...
IntPoint ip = CalculateXY(12);
Console.WriteLine(ip.X);
I would not advise using dynamic for this. If you do it the way I suggest above, that puts the compiler in your corner, working on your behalf to make sure that any code that calls your method knows what it's getting and uses it properly. dynamic is meant for other things, usually fairly exotic things -- I've known about it for years and never yet used it in production code.
Anonymous types, like in your original example, are virtually never returned from methods. That's exotic stuff too, for reasons you discovered already. It's a little more hassle to find a suitable return type sometimes (or write one, as we did above), but it's generally worth the effort.
UPDATE
Here's another option:
private void CalculateXY(int id, out int x, out int y) {
// bla bla bla
x = calX;
y = calY;
}
Call like...
int x, y;
CalculateXY(32, out int x, out int y);
It's not my absolute favorite, but it's an option that's strongly typed, properly named, and doesn't require writing a new class just to hold a return type. I wouldn't mind seeing that in code.
In comments, #KMoussa suggested Tuple<int,int> for a return type. That's feasible, and if it's a private helper function it's not the worst thing you can do, but if the code is being maintained the "Item2 who?" cost over time will exceed the up-front cost of writing a quickie class. Tuple was, IIRC, originally designed to do what anonymous types are now used for.

Is the order of member initializers in an object initializer deterministic? [duplicate]

Does the order in which I set properties using the object initializer syntax get executed in the exact same order?
For instance if I do this:
var s = new Person { FirstName = "Micah",
LastName = "Martin",
IsLoaded = true
}
will each property get set in the same order?
Yes.
Apologies for getting interrupted (I have to actually do some work every so often). The spec doesn't explicitly say it, but it makes it pretty clear IMO in section 7.6.10.2:
An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas.
(Note the word "sequence" here, rather than "set". I personally think that's significant, as a sequence is ordered.)
The following class represents a point with two coordinates:
public class Point
{
int x, y;
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
}
An instance of Point can be created and initialized as follows:
Point a = new Point { X = 0, Y = 1 };
which has the same effect as
Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;
where __a is an otherwise invisible and inaccessible temporary variable.
EDIT: I've had a response from Mads Torgersen, who has basically said that anything which can be done now will preserve the order. There may be some oddities in future where the order is not preserved in weird cases where you're doing something other than setting a property/field, but that will depend on where the language goes.
It's worth pointing out that there are actually lots of steps going on here - there's the order of execution of the evaluation of the arguments (i.e. the RHS bits) and the order of execution of the assignments. For example, if you have:
new Foo
{
A = X,
B = Y
}
all the following orders are possible while still maintaining the order of the actual property execution (A and B):
Evaluate X, assign to A, evaluate Y, assign to B
Evaluate X, evaluate Y, assign to A, assign to B
Evaluate Y, evaluate X, assign to A, assign to B
I believe the first option is the one actually taken, but this was just to demonstrate that there's more to it than meets the eye.
I would also be very wary of actually writing code which depends on this...

C# Dynamic Instantiation

I am in need of some help here about doing a dynamic instantiation in C#. What I want to accomplish is to be able to use a string variable that is used as the name in the instantiation. I think you can use reflection or something, but I am lost on this one. Here is my test code snippet and hopefully someone has an answer.
Averages is tied to a class that handles everything. So lets say I wanted to make test the variable and everything that is tied to the string of test could be passed as the instantiation. How could I create an object that can handle the variable test coming in, compile and be used in runtime? I know this may sound out of the ordinary, but instead of me using many IF's with multiple declarations of doubles. I could use a dynamic instantiation. Anyone that can help out I would be most appreciative.
Averages test = new Averages();
double[] testresult;
testresult = test.sma();
womp,,,I want to dynamically declare arrays of doubles. I already know how to declare a static array. What I am trying to accomplish is eliminating declaring 30 arrays that bascially do the same thing over and over again with a different naming.
So instead of doing this:
if (UITAName == "SMA")
{
Averages sma = new Averages();
double[] smaresult;
smaresult = sma.sma(UITAName, YVal, UITPeriod, UITShift);
chart1.Series[UITA].Points.DataBindXY(test2, test1);
}
if (UITAName == "TMA")
{
Averages tma = new Averages();
double[] tmaresult;
tmaresult = tma.tma(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, tmaresult);
}
else
if (UITAName == "EMA")
{
Averages ema = new Averages();
double[] emaresult;
emaresult = ema.ema(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, emaresult);
}
I want to do this only once for everything instead of doing IF statements. The problem is that you cannot compile with a declaration of a string. There has to be a way I just do not know how.
Averages UITAName = new Averages();
double[] UITANameresult;
UITANameresult = UITAName.UITAName(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, UITANameresult);
You can instantiate a class dynamically using Reflection, with Activator.CreateInstance.
Activator.CreateInstance("MyAssembly", "MyType");
However I'm not entirely clear on what you're trying to do. If you already have a class called Averages, what do you need dynamically instantiated? And I'm a bit worried by what you mean that it's "tied to a class that handles everything"...
Sounds like you might need to check out Func<> ??? Just my initial assessment without seeing a little more code to give me a clearer context.
To clarify, if you are wanting to pass the values as an argument, like you would on your command line, then you would need to instance the assembly. Otherwise, with Func<T, TResult> you can pass parameters dynamically to a method and get the return value.
Okay...if I get what you are saying...you want something that would resemble:
class Average
{
public double[] sma()
{
// do something
return dArray;
}
public double[] ema()
{
// do something
return dArray;
}
}
that is...the function 'name' would be the value of the string returned from a database query of some sort?
...and if that is the case then I don't know why you wouldn't just do a dictionary like:
Dictionary<string, double[]> testResults = new Dictionary<string, double[]>();
void GetDoubles(string name, params double[] args)
{
testResult[s] = GetAverages(args);
}
I think this could help you.
If i understand you correctly, you have method initinialization values in db as SMA,EMA,etc and you need to invoke the method at runtime,
string invokeMethod = GetValueFromDB() //ur logic to get the SMA or EMA or TMA from db
Type urType=typeof("yourclassname");
object unKnownObj = Activator.CreateInstance(urType);
//Fill your paramters to ur method(SMA,EMA) here
//ie, sma.sma(UITAName, YVal, UITPeriod, UITShift);
object[] paramValue = new object[4];
paramValue[0] = UITAName;
paramValue[1] = YVal;
paramValue[2] = UITPeriod;
paramValue[3] = UITShift;
object result=null;
try
{
result = urType.InvokeMember(invokeMethod, System.Reflection.BindingFlags.InvokeMethod, null, unKnownObj, paramValue);
}
catch (Exception ex)
{
//Ex handler
}
So this way you can avoid the multiple if loops and will invoke the method directly by the given name..
I think reflection might not be the best solution for your situation. Maybe decomposing your code a little bit might help, something along the following lines...
public interface ICalculation
{
double [] Calculate(double y, double period, double shift);
double XVal {get;}
}
public class SMA : ICalculation
{
public override double[] Calculate( double y, double period, double shift )
{
// do calculation, setting xval along the way
}
// more code
}
public class EMA : ICalculation
{
public override double[] Calculate( double y, double period, double shift )
{
// do calculation, setting xval along the way
}
// more code
}
public class Averages
{
public void HandleCalculation( ICalculation calc, double y, double p, double s )
{
double[] result = calc.Calculate( y, p, s );
chart.Series[UITA].Points.DataBindXY( calc.XVal, result );
}
}

Categories