Is the best way to reference these object properties? - c#

Just wondering if this is the most eloquent way to write this code:
var myObj = new Class();
int myId1 = myObj.Id1;
int myId2 = myObj.Id2;
Was trying to do it in 2 lines like:
int myId1 = new Class().Id1;
int myId2 = new Class().Id2;
But I suspect this is more inefficient as instantiating 2 objects instead of 1.
So what is the leanest way to write the above code.
Thanks.
EDIT.
I am trying to write a central bit of code, and chose to write it in a class. I am trying to insulate the application from the details as to how this values are acquired. From a comment below, it would seem that the use of a static class would be most eloquent.
EDIT2:
After thinking about this a little more, I think it is best if I do use a non static approach since I can populate the class properties in the constructor. So therefore I need one "new" and 2 accessor lines of code, so approach 1 seems best.

If you only want to assign myId1 to the default value of Class().Id1, and the same with 2, then you can do it your second way.
However, if you want to be assigning those two variables to the values of a manipulated Class object, then do it the first way.
Instantiating a whole new object just to get a second default value is wasteful.

Related

Dynamically change class call path?

In the code below, is it possible to dynamically call MyFunction() by changing OtherClass1 with strings a and b?
string a = "OtherClass1", b = "OtherClass2";
myClass = new MyClass();
myClass.OtherClass1.MyFunction();
Something like this:
myClass.a.MyFunction();
Tried to dynamically change it but cant figure out how...
While this is possible to solve this with reflection, it is not something I would recommend, especially not for someone new to coding. You are opting out to all kinds of protections the compiler will give you, and greatly increase the risk of bugs. But if you absolutely want to shoot yourself in the foot you can check out Get property value from string using reflection and How to Invoke Method with parameters.
My recommendation would be to instead make the two classes share an interface, and use an enumerable to select one of them:
public enum MyClasses{
Class1,
Class2
}
public IMyClass GetClass(MyClasses obj){
return obj switch{
MyClasses.Class1 => OtherClass1,
MyClasses.Class2 => OtherClass2,
_ => throw new InvalidOperationException();
}
}
this can then be called with
myClass.GetClass(a).MyFunction();
It would be even better to avoid the problem in the first place, but this pattern can be useful in some cases. You could replace the enum with strings, but that would again increase the chance of mistakes and bugs. It is better to parse the string to an enum in some input layer, that lets you do all the data validation in one place, making the rest of the code more reliable.

How to declare an array of deserialized class parameters without initializing it?

I consider this as a continuation of what I've learned from my two previous threads. Instead of Javascript I will be using pure C#.
I have a class with 3 parameters in it, and I am creating a variable which is a result of deserialization to class type
var param = js.Deserialize<ClassName>(jqData.Params);
Based on what I've learned from my first thread, it stores values based on inputs I've made within 3 textboxes that I have.
For our purposes, let's assume I only placed input in a second textbox out of three, so the values would be null, "abc", null.
Now, I got some very good suggestions from my second post, which I want to implement.
I want to create an array of objects, WITHOUT initializing, since those objects already hold values, reduce array down to 1 element based on criteria from that excellent post, and then proceed with my validation logic.
However, I am struggling with declaring array part. From what I saw here in SO, most of threads are talking about declaring and initializing those elements. I don't need it.
What I need is to declare an array, which would have class elements in it, something like array = [param.elem1, param.elem2, param.elem3], and when I run a code, it will return [null, "abc", null].
Can you please point me in the right direction on how to properly declare such array?
Your idea was close to how this can be handled. Just change your array = [param.elem1, param.elem2, param.elem3] to:
var myArray = new object[] { param.elem1, param.elem2, param.elem3 };
If you know the type of param.elem1/2/3, you can use the specific type (e.g. string[] instead of object[]).

Can you make an element and an element-in-a-list act like the same object?

I know from questions like: "Is it Possible to store references to objects in list?" that you can modify a property on an object without removing the object from a list. So you can make a wrapper class and put your object inside it, then modify the value. However, if what you are trying to do is change the object itself...
What I want to know is: Can you make a series of objects, store them in a list like structure, and then access them from either the list or the objects? Can you make object and the object-in-the-list act like they are the same object? Can you do this if you use an array?
Using System;
Using System.Collections.Generic;
Namespace Project1
{
Class Test
{
Public static void Main()
{
int one = 1;
int two = 2;
int num = 3;
List<int> myList = new List<int>();
myList.Add(one);
myList.Add(two);
myList.Add(num);
myList[2] = 4; // I want this to also set num to 4
num = 5; // I want this to also set myList[2] to 5
Console.WriteLine(myList[2]); //prints 4
Console.WriteLine(num); //prints 5
}
}
}
Looking at your code example, I think I understand what you are getting at. Basically, you want to access the element in the array directly and not by the indexed property accessor. It's very simple to do that, as long as the item in the array is a reference type. However, this won't work with value types, because the standalone variable and the indexed property are pointing to different memory storage spaces when value types are involved.
To illustrate:
listOfPersons[2] = new Person { Name = "Homer Simpson", Age = 35 };
Console.WriteLine(listOfPersons[2].Name); // will show Homer Simpson
Person myself = listOfPersons[2];
myself.Name = "Bart Simpson";
Console.WriteLine(myself.Name); // will show Bart Simpson
Console.WriteLine(listOfPersons[2].Name); // will show Bart Simpson
Console.WriteLine(listOfPersons[2].ReferenceEquals(myself)); // will show true
On the other hand:
listOfInts[2] = 2;
Console.WriteLine(listOfInts[2]); // will show 2
int myInt = listOfInts[2];
myInt = 5;
Console.WriteLine(myInt); // will show 5
Console.WriteLine(listOfInts[2]); // will show 2...
Hope this helps!
First, your code doesn't have any objects except the List object you created. Integers are not objects. You could box the integers, but C# will copy on both boxing and unboxing so you couldn't use that for what you are asking.
In general, to get the behavior you're looking for, you need to use a reference type (i.e. an object) that exposes a property of the type you want to use. Note, however, even for reference types, you can absolutely have two references that refer to the same object, but the references themselves are distinct - so changing one reference to refer to a different object won't change what the other reference is referring to.
You can pass parameters by reference to a method or function call, but you can't store this reference (not even by trying to close over it with a lambda), so you can't keep a reference in a list and use it to update the variable that was added to the list.
You could mock up a very cludgy workaround where you maintained a list of Func<T>/Action<T> getter/setter pairs and use lambdas to close over the original variable before you add it to the collection, but if you're going to that level, you are long past the point where you should take a step back and figure out why you're taking the path of most resistance.
Simply put, this isn't the kind of thing you really should find yourself needing to do - and if it's something you encounter, it might be a sign you've missed another, better way to architect your code.

Replace object but keep previous memory location in c#

Let's say I have a list:
List<object> list = new List();
list.Add(object1);
list.Add(object2);
object foo = list[0];
How do I make a call to list to replace list[0] such that foo will automatically point to the newly replaced object?
I know this line won't do the trick as foo will continue pointing to the old value of list[0]...
list[0] = object3;
Thanks!
It's not possible in my opinion. You need an additonal level of indirection which you have to implement yourself.
You could use a delegate/ anonymous lambda that fetches list[0]:
Func<object> foo = () => list[0];
Of course that changes the syntax slightly since it's now foo() instead of foo but it has the effect that you can fetch the value of list[0] at any time later and it always gets the current value.
What you really want to be able to do is to override the assignment operator but that's not possible in C#. The closest you'll get is to create a class that behaves a bit like Nullable<T> having a .Value property on it and assign to that .Value property instead of overwriting the object itself in the list.
You can use the fixed keyword but only in unsafe code. But i'm not sure what your attempting to do so it may not suite your needs if you need this level of control c++ cli would be a better choice.
Unsafe pointers are one possibility: http://msdn.microsoft.com/en-us/library/y31yhkeb(v=vs.80).aspx
For "safe" code, you can do something like store your value in an array of length 1, and then only store references to the array and always access the value by array[0], but this is a bit of a hack and there is probably a better way to do what you want to accomplish.

C# and storing reference to method parameter

For a little background information, I've got an application that's running in a loop, and over ever tick it calls a method Tick. There's a bunch of classes that extend a base class and all have their own tick methods, and get added to a dependency chain so that say when class A gets called and it's chain has instances of B and C in it, B.Tick gets called, followed by C.Tick, and then finally A.Tick.
So in pseudo code my class kind of looks like this:
public class A : Super
Super b;
Super c;
ArrayList one;
ArrayList two;
tick(){
one.Add(b.LastValue);
two.Add(c.LastValue);
... do something with one and two ...
}
A(){
b = new B(some other array list);
c = new C(ref one);
}
B is working fine, and always gets the correct value. The problem is I guess you can't store a reference to another variable in a class, so when I do new C(ref one); and the contructor for C is setting a class variable to one, later on after one is updated in A it's like C no longer knows that its still supposed to be pointing towards one (which is now updated) and is just empty (like it originally was inside the constructor). Any idea on how to achieve what I'm looking to do, without having to use C# pointers and unsafe code? Thanks, hopefully it makes sense :)
Edit:
Apparently people can't answer questions with confusing pseudo code that is completely unrelated to the actual question, so changed extends to :
Edit 2: C class
...
ArrayList local;
...
C(ref ArrayList one){
local = one;
}
Tick(){
LastValue = local[0] + 5; //not actual formula, just shows trying to use a referenced variable
}
Since one is an ArrayList, you can only pass it as a reference. You are now apparently passing it as a reference-to-a-reference to the constructor. You may not need that ref.
But please show a more complete idea of what you are trying to accomplish.
Edit:
After seeing your C class, there is no need for the ref. c will share the instance of the ArrayList that A calls one.
This seems to boil down to the general referencetype/valuetype issue in .NET. To summarize:
instances of objects do not have a name and cannot (physically) be passed as parameter at all.
you always access an instance through a reference. In your code, one (2x) , two, local are all references to Arraylist instances.
the references themselves behave like valuetypes, ie assignment means copying.
To learn more about referencetypes/valuetypes, search for 'copy semantics' and avoid postings that start with 'valuetypes exist on the stack'.
There's nothing to prevent you from doing this. Whether or not it's a good idea is another question though. In general, I'd recommend trying to avoid changing state between method calls if you can avoid it. Of course, the key expression there is "if you can avoid it". :-)
you can't store a reference to another variable in a class
You can, people do it all the time. Simply assign it to a (private) field.
so when I do new C(ref one); [snip /] later on after one is updated in A it's like C no longer knows that its still supposed to be pointing towards one
Actually, it does know that, but you should assign one to a member field. Assigning to objects is nothing more then setting a reference to the object. Changing the object, changes them everywhere you've assigned it:
class A
{
public string Hello { get; set; }
}
class C
{
private A myA;
public C(A a) { myA = a; }
public A GetMyA() { return myA; }
}
// somewhere else:
A someA = new A();
someA.Hello = "Hello World";
C someC = new C(someA);
someA.Hello = "Other World";
Console.WriteLine(someC.GetMyA().Hello);
// this will print "Other World" and not "Hello World" as you suggest
PS: since you were posting pseudocode, I hope you don't mind me simplifying it a bit. If I misunderstood your question, then please disregard (and perhaps clarify, if possible).
PPS: rereading your (edited) code and still trying to figure out what the problem is, there seems to be nothing that prevents C in your code from keeping a member with a reference to A and calling a.Add will obviously reflect the member variable in c as well. Indeed, no need for ref here.

Categories