I'm trying to return a reference to an object, not pass it by value. This is due to not being able to pass a property by reference.
How can I get the code below to write 'new number plate' not 'old number plate'. After a bit of looking it seems like I cant. Just wanted to be sure first. Seems odd you cant.
Cheers
Steve
http://hardcode.ro/archive/2008/03/18/c-return-reference-types.aspx
Link
public partial class Test2 : DefaultPage
{
protected void Page_Load(object sender, EventArgs e)
{
var car = new Car();
var numberPlate = car.GetNumberPlate();
numberPlate = "new number plate";
Response.Write(car.GetNumberPlate());
}
}
}
public class Car
{
private string _numberPlate;
public Car()
{
_numberPlate="old number plate";
}
public string NumberPlate
{
get { return _numberPlate; }
set { _numberPlate = value;}
}
public string GetNumberPlate()
{
return _numberPlate;
}
}
You're doing this a little backwards. If you want to change the value for that you need to actually change the property on the object.
car.NumberPlate = "old number plate";
Response.Write(car.GetNumberPlate());
If you're wanting to work with references you can use the ref keyword. This may not be what you're looking for though.
You need to become clearer in your mind about the difference between objects and references. Your property already returns a reference to the string containing the current numberplate. It can't possibly return the object itself, because string is a reference type. (Even if you used a value type, the property would only be returning a copy of the data, so change to the variable's value still wouldn't affect the property.)
What you seem to want isn't a reference to the object but a reference to the property. There's no way of doing that in C# - and this is a good thing in my view, as it promotes readability. The kind of code you're trying to write in your example is much more complicated to understand, because assigning a value to a normal variable could do anything.
For more information, see my article about value types and reference types.
protected void Page_Load(object sender, EventArgs e)
{
var car = new Car();
car.NumberPlate = "new number plate";
Response.Write(car.NumberPlate);
}
Your GetNumberPlate() method seems superfluous.
If you're using C# 3 or 3.5, I would rewrite this as:
public partial class Test2 : DefaultPage
{
protected void Page_Load(object sender, EventArgs e)
{
var car = new Car();
car.NumberPlate = "new number plate";
Response.Write(car.NumberPlate);
}
}
public class Car
{
public Car()
{
NumberPlate="old number plate";
}
public string NumberPlate { get; set; }
}
Since strings are immutable you can't do this. The value that you get back in this line:
var numberPlate = car.GetNumberPlate();
Is a reference to all intents and purposes (in that the value of the string is not copied to a different memory address), but this line
numberPlate = "new number plate";
Is semantically the same as:
numberPlate = new string("new number plate");
Which causes that reference to point to a different string.
Are you looking to pass the property the same way you might pass a method into a function? For methods you'd do something like this;
// fn takes a method which returns string, calls it, and prints it.
void PrintsAMethodsResult(Func<string> GetString)
{
Console.WriteLine( GetString() );
}
// calls like this;
PrintsAMethodResult( Car.GetNumberPlate );
But if you want to do it with a property, you've got a bit of a mess; properties are really just two methods (a getter and a setter, of type Func<T> and Action<T>) so you have to write different things do deal with the setter and the getter. A getter property can be called like this;
PrintsAMethodResult ( () => Car.NumberPlate );
This works the same as the GetNumberPlate method, by creating a function which takes no parameters and returns the car's number plate, effectively converting the property into a function.
There is no nicer way of passing the getter property as though it were a method.
Create another class within "Car" and then return it. That should do just fine. Although possibly you don't want to this since it's not a good way to code.
Related
I have a class that has a field that is being assigned a value from multiple methods.
public class Shape
{
private Point2D m_location;
public void Move()
{
m_location = ...
}
public void Rotate()
{
m_location = ...
}
public void Flip()
{
m_location = ...
}
}
I am getting a warning from NDepend that says:
Don't assign a field from many methods
https://www.ndepend.com/default-rules/Q_Don't_assign_a_field_from_many_methods.html
I am thinking of solving this problem by creating a separate method to assign the value of the field and calling this method from the other methods that currently assign a value to the field.
Here is an example of the code:
private void SetLocation(Point2D point)
{
m_location = location;
}
I want to know if this is a valid way to solve the problem and if it will just hide the code-smell that NDepend detected or actually fix the issue.
Is this a valid way to solve this problem?
No. As you suspect, this is a code smell. What NDepend is complaining about is mutable references; you have code where:
var s = new SomeObject(someInitialization);
var r = s.SomeResult();
// you now have no idea what s contains or if it is even usable any more.
The solution to this is to make SomeObject immutable and return new references instead of changing internals:
public SomeObject Something()
{
return new SomeObject(SomethingDifferentDependingOn(this.something));
}
Now instead of your first example you have:
var s = new SomeObject(someInitialization);
var r = s.Something().Result;
// s is guaranteed to be unchanged.
Yes some times you will need mutable references. In those cases; document them and explain why they have to be mutable. Then you can override NDepend rules on a case-by-case basis to prevent it showing a warning. If you have a code smell, warn people. Do not try to hide it.
The example after your edit is quite different, but the general principle still holds. If you have only a few internal fields that all change in method calls you can still return immutable references, e.g.:
public Shape Move()
{
return new Shape(m_location ...);
}
If you have many internal fields that don't all change, or you need to do something like share private fields you can't easily have immutable reference, but you can still avoid the warning by using accessors:
public Location
{
get { return m_location; }
private set { m_location = value; }
}
Then use Shape.Location exclusively in your internal methods.
Rephrased the question. Scroll down for the original
Ok, maybe I should have given you the whole picture. I have many classes which look like this:
public class Movement : Component
{
private Vector3 linearVelocity;
public Vector3 LinearVelocity
{
get
{
return linearVelocity;
}
set
{
if (value != linearVelocity)
{
linearVelocity = value;
ComponentChangedEvent<Movement>.Invoke(this, "LinearVelocity");
}
}
}
// other properties (e.g. AngularVelocity), which are declared exactly
// the same way as above
}
There are also classes called Transform, Mesh, Collider, Appearance, etc. all derived from Component and all have nothing but properties which are declared as described above. What is important here is to invoke the ComponentChangedEvent. Everything works perfectly, but I was looking for a way where I don't have to rewrite the same logic for each property again and again.
I had a look here and liked the idea of using generic properties. What I came up with looks like this:
public class ComponentProperty<TValue, TOwner>
{
private TValue _value;
public TValue Value
{
get
{
return _value;
}
set
{
if (!EqualityComparer<TValue>.Default.Equals(_value, value))
{
_value = value;
ComponentChangedEvent<TOwner>.Invoke(
/*get instance of the class which declares value (e.g. Movement instance)*/,
/*get name of property where value comes from (e.g. "LinearVelocity") */);
}
}
}
public static implicit operator TValue(ComponentProperty<TValue, TOwner> value)
{
return value.Value;
}
public static implicit operator ComponentProperty<TValue, TOwner>(TValue value)
{
return new ComponentProperty<TValue, TOwner> { Value = value };
}
}
Then I would use it like this:
public class Movement : Component
{
public ComponentProperty<Vector3, Movement> LinearVelocity { get; set; }
public ComponentProperty<Vector3, Movement> AngularVelocity { get; set; }
}
But I am not able to get the instance where LinearVelocity comes from nor it's name as string. So my question was, if all of this is possible...
But it seems that I have no option other than keep doing it the way I was, writing this logic for each property manually.
Original Question:
Get instance of declaring class from property
I have a class with a property:
public class Foo
{
public int Bar { get; set; }
}
In another context I have something like this:
Foo fooInstance = new Foo();
DoSomething(fooInstance.Bar);
Then, in DoSomething I need to get fooInstance from having nothing but parameter. From the context, it is save to assume that not any integers are passed into DoSomething, but only public properties of ints.
public void DoSomething(int parameter)
{
// need to use fooInstance here as well,
// and no, it is not possible to just pass it in as another parameter
}
Is that possible at all? Using reflection, or maybe a custom attribute on the property Bar?
Why do you want to send just a property to DoSomething, send it the whole object :), so it would become,
DoSomething(fooInstance);
Your function will then accept object instead of parameter. You can use an overload of this function to make sure that old code doesn't break.
There are several ways to deal with implementing INotifyPropertyChanged. You're doing almost the same thing, except you don't implement the interface and raise the event in a different way. But all of the solutions apply for you too.
Like you do, call a method with a string parameter: OnPropertyChanged("Property").
Call a method with a lambda that uses the property: OnPropertyChanged(() => Property). The advantage of this is that it's compile-time checked for typos and refactoring-friendly.
Use caller information to inject the name of the property: OnPropertyChanged(). This will work in C# 5.
Use something like Castle DynamicProxy to create a derived class at runtime that will call the method for you. This means you need to make your properties virtual and that you need to create instances of the class only through Castle.
Use an AOP framework to modify the code of your properties after compilation to call the method.
there's no way to get fooInstance from parameter. parameter is passed by value, and is only a copy of the value of fooInstance.Bar, it no longer has anything to do with fooInstance
That being said, the obvious solution is to write DoSomething like this
public void DoSomething(Foo parameter)
{
// need to use fooInstance here as well,
// and no, it is not possible to just pass it in as another parameter
}
Property is just a field, which returns reference to some object on heap (i.e. its address). If property is not of reference type, it returns value of object.
So, when you do something like
DoSomething(fooInstance.Bar);
You just passing address of object Bar to method.
If Bar is reference type (i.e. class). Imagine that Mr.Foo has an address of Mr.Bar (462 for Marion County, Indiana). Mrs.CLR asks Mr.Foo for address of Mr.Bar. And then tells this address to somebody who needs address of Mr.Bar. How somebody will know, that CLR asked Foo about address of Bar? He received only an address 462 for Marion County, Indiana.
In case of value objects (int, double, structs etc), Mr.Foo has a cool mp3 track named Bar. Mrs. CLR creates a copy of that mp3 track and sends it to somebody. How somebody will know, that his mp3 track Bar is a copy of Mr.Foo's track?
So, if you want somebody to know about Mr.Foo, you need to pass an address of Mr.Foo to him:
DoSomething(fooInstance);
With this address somebody can visit Mr.Foo and ask him about address of Mr.Bar, or create a copy of his mp3 track :)
Is there a way in C# to create a field which is a reference to another field which is a value type?
class myClass
{
bool b1;
public void method1(ref bool b)
{
b1 = b;
}
}
I want b1 to reference the value of b, just as b references the value of the original argument, so that changes to b1 will affect the original argument.
EDIT:
What I’m trying to achieve is a myCheckBox class which automatically updates a field. See: How do I change a value argument from within an event handler?
Sure! Take a look at Eric's answer to this question:
Setting a ref to a member field in C#
As others have pointed out, you cannot store a reference to a variable
in a field in C#, or indeed, any CLR language.
Of course you can capture a reference to a class instance that
contains a variable easily enough
Well... there is a very contort way :) of course.
That is, using reflection!
You cannot get the address of a field, but we can use reflection.
Reflection is slower than accessing directly a field, i warn you.
And really, accessing private fields of other classes is a really bad practice!
Is however useful sometime for some dirty hacks when you don't have control of code written by other people.
Here the example, but i keep saying, it is not a good practice, is here only for curiosity and for educational purposes!
Fine another way to access your field, using properties or using a class that modify your properties.
// Our FieldReference class that internally uses reflection to get or set a field value.
public class FieldReference<T>
{
private object ownerObject;
private FieldInfo fieldInfo;
public FieldReference(object ownerObject, string fieldName)
{
this.ownerObject = ownerObject;
this.fieldInfo = ownerObject.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
public FieldReference(object ownerObject, FieldInfo fieldInfo)
{
this.ownerObject = ownerObject;
this.fieldInfo = fieldInfo;
}
public T Value
{
get { return (T)this.fieldInfo.GetValue(this.ownerObject); }
set { this.fieldInfo.SetValue(this.ownerObject, value); }
}
}
// Our dummy class
public class MyClass
{
// Our field we want to expose.
private int myField;
public MyClass(int value)
{
this.myField = value;
}
// Just a function we use to print the content of myField.
public override string ToString()
{
return this.myField.ToString();
}
}
class Program
{
public static void Main()
{
// We create our class.
MyClass mc = new MyClass(5);
// We print field value, should be 5 :)
Console.WriteLine(mc.ToString());
// We create our field reference
FieldReference<int> fieldref = new FieldReference<int>(mc, "myField");
// We set the value using field reference.
// Note, we accessed a private field :)
fieldref.Value = 100;
// Now we print the value, should be 100!
Console.WriteLine(mc.ToString());
Console.ReadLine();
}
}
Looks like something that is better solved using delegates/events.
Instead of trying to do the impossible (force value types to behave as reference types), use an event and fire it whenever this value is changed.
Subscribe to this event from the caller/s and you are good to go.
Not knowing what you would want this for you could use a delegate for this, it does sound like a code smell though:
class myClass
{
Action<bool> modify;
public void method1(Action<bool> modify)
{
this.modify = modify;
}
public void ModifyIt()
{
modify(false);
}
}
bool b1 = true; //b1 is true
var m = new myClass();
m.method1(val => { b1 = val; });
m.ModifyIt(); //b1 is false now
1) I'm still quite new to programming and have read a bit about getters and setters. But I really don't understand why they are used.. Could anyone explain it, or point me to an article? (The ones I read were not really understandable for me...)
2) In my current project I have a class where I declare and initialize an array of structs. I now need to access the array from another class, but it gives me the error: An object reference is required to access non-static member 'BaseCharacter.Attributes'.
I figures this could mean I need to use getters and setters? But how does this work for arrays?
Thanks in advance!
Simon.
EDIT: 2nd question got solved, which brings me to something else. When I want to use some class in another one, I'm making a new instance of the class, right? And this means I get the original values?
But that's not what I want.
The second class is used to generate the UI, and needs the values I'm keeping in the first class.
At some point I will implement save files (XML or even on a server in later stage). Can I then just get the values from those files?
For the getters and setters (the things that use them are called Properties) it's just a convenient and nice-looking way to make people think they're using a variable, but to do some computation whenever the variable is updated or accessed. For instance:
BankAccount.Interest
looks better than
BankAccount.GetInterest()
Even though you can calculate the interest at the time it is requested in both cases.
They are also used to make a variable be able to be accessed from outside the class, but changeable only from within the class with this technique:
public double Interest {
get;
private set;
}
For an example of a setter being used, if you've ever used Windows Forms and updated a control's Height or Width property, you're using a setter. While it looks like you're using a normal instance variable like c.Height = 400, you're really letting c update it's position by redrawing at a new place. So setters notify you exactly when a variable is changed, so your class can update other things base on the new value.
Yet another application of Properties is that you can check the value people try to set the property to. For instance, if you want to maintain an interest rate for each bank account but you don't want to allow negative numbers or numbers over 50, you just use a setter:
private int _interestRate = someDefault;
public int InterestRate {
get { return _interestRate; }
set {
if (value < 0 || value > 50)
throw new SomeException(); // or just don't update _interestRate
_interestRate = value;
}
}
This way people can't set public values to invalid values.
For your second question, you can do one of two things depending on what you're trying to do.
One: You can make that member static. That means that just one of them exists for the entire class instead of one per instance of the class. Then you can access it by ClassName.MemberName.
You can do that this way:
// inside the BaseCharacter class definition:
public static SomeStruct[] Attributes = new SomeStruct[size];
// then to use it somewhere else in your code, do something with
BaseCharacter.Attributes[index]
Two: You have to make an instance of the class and access the array through that. This means that each object will have its own seperate array.
You'd do that like this:
BaseCharacter bc = new BaseCharacter();
// use bc.Attributes
The second one is probably what you'll want to do, since you probably will want to modify each character's attributes seperately from all the other characters.
Actually the error you mention is not related to the getters and setters concept, it's because after creating your class you need to create an object before using its members; think of the class as a template for a document and the object as the document
you are most likely doing something like this:
var someVar = BaseCharacter.Attributes;
When you should be doing something like this:
var someVar = new BaseCharacter();
var someOtherVar = someVar.Attributes;
And about why the getters and setters, Seth Carnegie's Answer covers it nicely.
If you are new to Object Oriented Programming, you may be missing an important concept, that is about encapsulation.
Fields (attributes) of a class should be accessed only from within the class (or it's inherited classes). That is, if we have a class person, only with a name, you can do
public class Person
{
public string Name;
}
So anywhere in your program, you will be able to access it by doing:
Person person = new Person();
person.Name = "Andre";
This works, but it's not encapsulated. In some languages like C++ or Java, it was done like this:
public class Person
{
private string _name;
public string setName(string newName)
{
this._name = newName;
}
public string getName()
{
return this._name;
}
}
Person person = new Person();
person.setName("Andre");
This makes our _name attribute encapsulated, it can only be retrieved by it's get and set methods (that is, by the interface of the class).
C# makes this easier, allowing getters and setters:
public class Person
{
private string name;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
}
Person person = new Person();
person.Name = "Andre";
This is very much like the second example (Java/C++ way), but you treat Name as property, instead of methods, and leaving our name property encapsulated
1) They might seem optional but they allow you more control over code:
You're able to intercept new values and avoid them being set (e.g. to exclude pointless values). Also you're able to fire custom events in case a property is changed or updated (just like the WinForms controls do).
private string name;
public string Name
{
get
{
// running additional code, e.g. here I avoid returning 'null' for a name not set
if(name == null)
return "(Unknown)";
return name;
}
set
{
// checking incoming values, e.g. here I avoid setting an empty name
name = value != null && value.Length > 0 ? name : null;
// running more/additional code, e.g. here I raise an event
if(OnNameChange)
OnNameChange();
}
}
2) Without knowing the code it's hard to tell you the exact reason, but if you'd like to access some member variable or property you have to either create an object of that class or make the variable static (e.g. shared between all instances of the object):
class MyClass
{
public static int someNumber = 55;
public int thisNumber;
}
// ...
int someothervar = MyClass.someNumber; // access the static member variable
MyClass mc = new MyClass(); // create an object of the class
int yetanothervar = mc.thisNumber; // access the member variable
Could you please explain the following behavior of C# Class. I expect the classResult as "Class Lijo"; but actual value is “Changed”.
We’re making a copy of the reference. Though the copy is pointing to the same address, the method receiving the argument cannot change original.
Still why the value gets changed ?
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
String nameString = "string Lijo";
Person p = new Person();
p.Name = "Class Lijo";
Utilityclass.TestMethod(nameString, p);
string classResult = p.Name;
Response.Write(nameString + "....." + classResult);
}
}
public class Utilityclass
{
public static void TestMethod(String nameString, Person k)
{
nameString = "Changed";
k.Name = "Changed";
}
}
public class Person
{
public string Name
{
get; set;
}
}
Update: When I pass a String, it does not get actually changed.
The briefest answer is: read my article on parameter passing which goes into this in a fair amount of detail.
The slightly longer answer is to compare these two methods, both of which use value parameters:
public void ChangeMe(string x)
{
x = "changed";
}
public void ChangeMe(Person x)
{
x.Name = "changed";
}
In the first case, you are changing the value of the parameter. That is completely isolated from the original argument. You can't change the content of the string itself, because strings are immutable.
In the second case, you are changing the contents of the object which the parameter's value refers to. That's not changing the value of the parameter itself - it will be the same reference. To give a real world example, if someone delivers something to your house that changes the contents of your house, but it doesn't change your house's address.
If you changed the second method to this:
public void ChangeMe(Person x)
{
x = new Person("Fred");
}
then the caller wouldn't see any change. This is closer to what you're doing with a string - you're making the parameter refer to a different object, rather than changing the contents of the existing object.
Now, when you use a ref parameter, the variable used by the caller as the argument is "aliased" with the parameter - so if you change the value of the parameter, that changes the value of the argument as well. So if we change the last method like this:
public void ChangeMe(ref Person x)
{
x = new Person("Fred");
}
then:
Person y = new Person("Eric");
ChangeMe(ref y);
Console.WriteLine(y.Name);
this will print out "Fred".
The key concept to understand is that the value of a variable is never an object - it's either a value type value or a reference. If an object's data is changed, that change will be visible through other references. Once you understand that copying a reference isn't the same as copying an object, the rest falls into place reasonably easily.
Person is a reference type, so no matter whether you use ref, out or nothing, you will always be able to modify it inside the method. You never pass the real person object to the method, you are passing the pointer as reference but not the actual Person. The ref keyword is useful with value types (such as structs, int, float, DateTime, ...). It could also be used with reference types but only to indicate behavior but cannot enforce it. If you use it with reference types it allows you to change the object this reference is pointing to.
When you pass P to a test method you pass its location in the memory, rather than the copy of the object. Reference gets picked up in the body of the method and the original value gets modified.
Utilityclass.TestMethod cannot change the local variable p to point to a different Person object since you are not passing by reference, but it is still free to call any methods or change any properties on the object it is passed. So the Name property can be modified within Utilityclass.TestMethod.
This question has been mostly answered, but I think you might like to try out this snippet (bonus points if you try this out with ints!)
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.Name = "Class Lijo";
Utilityclass.TestMethod(p);
string classResult = p.Name;
Console.WriteLine(classResult);
Utilityclass.TestMethod2(ref p);
classResult = p.Name; // will bomb here
Console.WriteLine(classResult);
}
}
public class Utilityclass
{
public static void TestMethod(Person k)
{
k.Name = "Changed";
k = null;
}
public static void TestMethod2(ref Person k)
{
k.Name = "Changed Again!";
k = null;
}
}
When you pass a reference type argument to a method, this means that the method has direct access to that argument not to a copy of it....
So the result is Changed.