Why is the parameter is not updated? - c#

I have a class that uses another class.
The first class have this method:
public void myMethod()
{
//Parameters are an enumeration.
// Really is a exchange variable between this class
//and the other class.
Paramters myParameter = Parameters.Option1;
MyClass2 myOtherClass = new MyClass2(myParameter);
}
The second class:
public enum Parameters { Option1, Option2, Option3 }
MyClass2
{
Parameters _myParameters;
Public MyClass2(Parameters paramParameters)
{
_myParameters = paramParameters;
}
private void clickButton()
{
_myParameters = Parameters.Option2;
this.Dispose();
}
}
What I what it is create a dialog and Parameters are an enumeration that is to serve as exchange between the main window and the dialog to notify about the selection in the dialog.
However, when in the clickButton I change the value of the _myParameters, it is not changed in the object that was passed as parameter in the constructor of MyClass2.
If instead of using an enumeration as exchange variable I create a class that has the enumeration, then I can get the selection. The exchange class would be like this:
class MyExchangeClass
{
Parameters myOption;
}
Then the code would be:
public void myMethod()
{
//Parameters are an enumeration.
// Really is a exchange variable between this class
//and the other class.
MyExchangeClass mySelection= new MyExchangeClass();
MyClass2 myOtherClass = new MyClass2(mySelection);
}
The second class:
public MyExchangeClass
{
Parameters enum MySelection { Option1, Option2, Option3 }
}
class MyClass2
{
MyExchangeClass _mySelection;
Public MyClass2(MyExchangeClassparamParameters)
{
_mySelection= paramParameters;
}
private void clickButton()
{
_mySelection.MySelection = Parameters.Option2;
this.Dispose();
}
}
In this way, the Class1, the main window, gets the updated value in the property of the class MyExchangeClass.
I would like to know why in the first solution the enumeration is not updated, because if it would possible, I would like to avoid the needed to wrap the enumeration in a class.

However, when in the clickButton I change the value of the _myParameters, is not changed in the object that was passed as parameter in the constructor of MyClass2.
No, it wouldn't be. The value was passed in by value - the two variables (myParameter and _myParameters) are independent variables. A change to one variable does not affect the other variable. This is how all types work in C#.
For changes to a parameter within a method to be seen by the caller, you could use a ref parameter, but that's not viable in your case as you're changing an instance variable which was originally populated via a parameter.
You could wrap the value in a mutable class, pass a reference to an instance of that class into MyClass2, and then mutate the object within MyClass2 - that change would be seen within your first class, because that would be changing the data within the object rather than the instance variable of MyClass2. It's hard to know whether or not that's actually a good solution though, as we have so little context - with names like MyClass and myMethod we have no clue as to the bigger picture of what this is trying to achieve.

In your first solution the value of the enumeration inside the class didn't change because enumeration is a value type, and this line:
_myParameters = paramParameters;
made a copy of paramParameters and _myParameters is a completely separate, standalone object.
In your second example, MyExchangeClass is a reference type, so this line:
_mySelection= paramParameters;
made _mySelection point to exactly the same object as paramParameters reference was referring to.
From the documentation:
Variables that are based on value types directly contain values. Assigning one value type variable to another copies the contained value. This differs from the assignment of reference type variables, which copies a reference to the object but not the object itself.
And an enumeration is a value type, ibidem:
The value types consist of two main categories:
Structs
Enumerations

Related

Navigating between ContentPages with Prism in Xamarin Forms maintains NavigationParameters

Using the NavigationParameters collection within Prism, we are passing an object from one ContentPage to another ContentPage which displays as a modal.
The modal allows a user to edit the data. If the user decides to cancel the edit form, we call:
NavigationService.GoBackAsync(null, true).
Once navigated back to the previous page, the original property that was passed through to the modal has updated with the edited values without setting it.
Are NavigationParameters passed as a reference within NavigateAsync? What’s the best way of preventing this from happening?
Using the NavigationParameters collection within Prism, we are passing an object [...] [Emphasis mine]
You are setting an object in the NavigationParameters. Instances of classes (objects) are passed by reference in C#, instances of structures are passed by value. For structures there are semantics to copy and compare values (i.e. all public properties are copied and compared respectively), but for classes there are no similar semantics.
Please see the documentation:
Because classes are reference types, a variable of a class object holds a reference to the address of the object on the managed heap. If a second object of the same type is assigned to the first object, then both variables refer to the object at that address.
In order to prevent the original object being updated, you'll have to copy the object before it is manipulated (I'd copy it before passing it, but you could copy it at the target site, too). If your class contains value type properties only, a shallow copy will suffice, i.e. you create a method (or property, but this might be misleading) that returns a new object of your class with all the values copied
class MyClass
{
int Value1 { get; set; }
float Value2 { get; set; }
public MyClass Copy()
{
var copy = new MyClass()
{
Value1 = this.Value1,
Value2 = this.Value2
}
return copy;
}
}
If you object contains reference types itself, you might have to create a deep copy
class MyClass
{
MyClass2 Reference { get; set; }
public MyClass Copy()
{
var copy = new MyClass()
{
Reference = this.Reference.Copy()
}
return copy;
}
}
Of course, those will have to implement a Copy() method, too.

C# define that a class instance can never be null (it only contains no data)

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;
}

passing objects as parameters

The application is printing 24 but shouldn't it be printing 18 when we know that without ref keyword only a copy of object is passed and no change is made to the original object.
I have created a class called myclass and an object me. age is a public variable in class myclass.
I have set me.age as 18 and through the method show I have changed it to 24.
class Program
{
static void Main(string[] args)
{
myclass me = new myclass();
me.age = 18;
show(me);
Console.WriteLine(me.age);
Console.ReadLine();
}
public static void show( myclass you)
{
you.age = 24;
}
}
class myclass
{
public int age;
}
Don't confuse the variable and what the variable points to.
When you have:
MyClass myVar = new MyClass();
MyClass myVar2 = myVar;
That will create only a single instance of an object, but 2 variables pointing to it.
The same thing is happening to your parameter: you is a copy of the variable me, but both point to the same object. So when you modify you.age, you are also modifying me.age.
In your function, if you then did
you = new myClass();
only then would me and you refer to different objects. If you did this, me would still point to the original object.
If you added ref to the parameter you, then if you did
you = new myClass();
then the variable me would be updated to point to that same object.
For objects, you need to separate the variable from what the variable points to.
It's printing the right thing.
myclass is an object, and the default behavior is to pass the reference of the object in C#, so when you don't specify anything, you pass the reference.
If you declare struct myclass though, you'll have the behavior you want, because structs aren't references by default.
You're probably confusing this with C++ classes. In C#, classes are reference types, which means that whenever you have a variable of a type that's class, that variable doesn't hold the object itself, it holds only a reference to it (you can think of it as a pointer). So, when you pass your object into a method, you actually pass a reference to that object. This means the behavior you're observing is correct.
C# also supports value types (unlike e.g. Java), which you create by using struct instead of class. If you changed myclass into a srtuct, you would get the behavior you expected.
You are confusing value types and reference types.
public void addTwo(int a)
{
a += 2;
}
...
int a = 5;
addTwo(a);
Console.WriteLine(a); // will give "5";
public void addTwo(ref int a)
{
a += 2;
}
...
int a = 5;
addTwo(ref a);
Console.WriteLine(a); // will give "7";
For reference types (anything that is defined as class instead of struct, what you are passing on is a reference to the object, not a copy. So you are in fact changing the object.
You are sending an object to your function.
Not an atomic type or a struct, therefor it is sent by reference (this is how C# works), anything you change in this object in the function will also change in the original object because it is the same.
More information about passing parameters: http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.71).aspx

object is really reference type?

As far as I know Class and Object are reference type.
I have below method to Change the Value
public void ChangeValue(MyClass classobj)
{
classobj.Number = classobj.Number*2;
}
I invoke the method to double the value
var myClass=new MyClass();
int myNumber = 10;
myClass.Number = myNumber;
ChangeValue(myClass);
And it will be return 20 which is fine as you can interpret it as when you make object of your class then it pass reference to method and it will update the reference values.
but my question is why its not happening for Object type. In other words why when I make object and assign some value to it like below
object myObject = new object();
string sometext = "Some object value";
myObject = sometext;
ChangeValue(myObject)
it wont change the value after executing the method
public void ChangeValue(object objectValue)
{
objectValue = null;
}
I know the parameter of methods are value types but can not understand it have different behavior for two reference type.
You're actually doing two different things here. Object and your MyClass are indeed both reference types, which means you pass a reference to the actual object into the ChangeValue method. However, the reference that you see inside the method is a copy of the reference the caller holds. They point to the same object, so when you manipulate the object in the method the caller of the method can see your changes, but changes to the actual reference inside the method only affect the method itself.
In an attempt to summarise, objects are passed by reference, but those references are passed by value.
In your method
public void ChangeValue(object objectValue)
{
objectValue = null;
}
What you're actually doing is reassigning the reference objectValue, and that reference is a copy of the reference called myObject which the caller has. Because the method only has a copy, it can't affect the caller's reference at all.
There is a way to make this work, you have to pass the reference by reference. Which always gives me a headache, but that's what the ref keyword is for.
public void ChangeValue(ref object objectValue)
{
objectValue = null; // this is the SAME reference as the caller has, so the caller will see this change
}
However then it also has to be called that way:
ChangeValue(ref myObject);
so that it's obvious at the call site that it might come back pointing to a different object. It's important to know that, as you might still have things relying on the old value and end up in a horrible confused mess if references were pointing to different objects unexpectedly.
You pass the objectValue to the ChangeValue(object objectValue) by value and this value is a reference. Then you change this value, but not the value of the myObject.
You have to pass it as ChangeValue(ref object objectValue) to actually pass the value of reference by reference.
It's not a different behavior, you're doing different things
This will work exactly as your object example:
public void ChangeValue(MyClass classobj)
{
classobj = null;
}
And this will work as your first example(assuming you will pass MyClass instance):
public void ChangeValue(object objectValue)
{
((MyClass)objectValue).Number *= 2;
}
What realy happens here is that when you are assigning parameter (not a property or field of parameter) you are only changing that parameter's value. Original value and variable in calling code stay intact.
The same happens here:
MyClass a = new MyClass();
MyClass b = a;
a = null;
// b still contains the value created in the first line
Simply speaking, reference variables hold the pointer (memory address) of the actual value.
By changing variable's value, you are making it point to different object or null.
But when you are doing a.field=2 this means you are taking the object a is referencing to and changing it's field member value.

Passing objects by reference or not in C#

Suppose I have a class like this:
public class ThingManager {
List<SomeClass> ItemList;
public void AddToList (SomeClass Item)
{
ItemList.Add(Item);
}
public void ProcessListItems()
{
// go through list one item at a time, get item from list,
// modify item according to class' purpose
}
}
Assume "SomeClass" is a fairly large class containing methods and members that are quite complex (List<>s and arrays, for example) and that there may be a large quantity of them, so not copying vast amounts of data around the program is important.
Should the "AddToList" method have "ref" in it or not? And why?
It's like trying to learn pointers in C all over again ;-) (which is probably why I am getting confused, I'm trying to relate these to pointers. In C it'd be "SomeClass *Item" and a list of "SomeClass *" variables)
Since SomeClass is a class, then it is automatically passed by reference to the AddToList method (or more accurately, its reference is passed by value) so the object is not copied. You only need to use the ref keyword if you want to re-assign the object the reference points to in the AddToList method e.g. Item = new SomeClass();.
Since SomeClass is a reference type, you do not need to use the "ref" keyword. If it were a value type, "ref" might be useful.
Think of out as a way of making a parameter work as a return value.
So these are very similar:
void Foo(out int result)
{
result = 5;
}
int Foo()
{
return 5;
}
And then think of ref as a way of allowing a parameter to be both an input and an output.
So in your example, if you declared your method:
public void AddToList(ref SomeClass Item)
Then the caller would have to write something like:
SomeClass i = null;
obj.AddToList(ref i);
This would be illegal, for example:
obj.AddToList(ref new SomeClass());
They would be forced to pass a variable name, rather than an expression, so that the AddToList method can store a value in the variable. By adding the ref prefix you are allowing your method to make the passed variable point to a different object.
If you ever need to use the original value of the parameter user ref. If not, use out. For reference:
http://www.yoda.arachsys.com/csharp/parameters.html
http://msdn.microsoft.com/en-us/library/0f66670z(VS.71).aspx

Categories

Resources