Let's say I have the following class:
public class MyClass {
public string FirstAttribute {
get {
return Attributes["FirstAttribute"];
}
set {
Attributes["FirstAttribute"] = value;
}
}
public string SecondAttribute {
get {
return Attributes["SecondAttribute"];
}
set {
Attributes["SecondAttribute"] = value;
}
}
public Dictionary<string, string> Attributes;
public MyClass(Dictionary<string,string> att) {
Attributes = att;
}
}
and I wanted to be able to obtain a pointer to the value that is stored in the Dictionary, so that I can get and set the values (yes unsafe) directly without having to wait for the Dictionary to search for the element by key every time.
Is there a way to do that in c#?
No, I don't believe so. You could store a mutable wrapper in the dictionary though:
public class Wrapper<T>
{
public T Value { get; set; }
}
Then create the dictionary (which should be private, by the way - public fields are a really bad idea other than for constants) as a Dictionary<string, Wrapper<string>>. You can then keep fields for the Wrapper<string> objects associated with "FirstAttribute" and "SecondAttribute".
Frankly I don't think this would be a particularly good idea - I'd just stick with the dictionary lookup - but it's an option. (Assuming nothing's going to change which wrapper is associated with the keys.)
Another option is simply to use fields for the two specific attributes - when you're asked to set a new value, set it in the dictionary and set a field. When you're asked for the current value, just return the value from the field. Of course, that's assuming that you're in control of the dictionary (i.e. so it can't change outside your class).
No, no, no, no.
strings are immutable for a reason. A string might be shared between multiple references: modifying it directly with unsafe code might lead to weird behavior.
A way to go around this would be to write a wrapper class that olds your value, and keep a reference to an instance of that wrapper. The getters and setters would then modify the wrapper's property.
If the values in the dictionary were mutable, you could grab the reference to them and mutate them. But strings are immutable. So the dictionary has its own copy of a reference to your string, and you can't alter the string it is pointing to. If you try to replace it with another string, you need to update the dictionary with the new reference. So basically there's no way to improve on what you have in this situation.
Related
First of all, I have read the question asking for the difference between fields and properties and I know what it is used for.
Now on to my question, I wanted to create a property where I am sure that get and set will both be empty, so I do get; set;. All good and well. But now I realised that I have just made a public field with a capital name, it is in all ways identical.
Even the argument of it being used so future code does not depend on implementation cannot be said, as I can simply make this a property and implement a getter or a setter. The semantics of a field and a property are identical outside the class it is defined in.
So my question is, should I use a field or a property when a property would simply use get;set;?
So this:
public IEnumerable<string> Products;
is identical in all ways to this:
public IEnumerable<string> Products { get; set; }
should I use a field or a property when a property would simply use get;set;?
Use a property... for the practical reasons below, and for the philosophical reasons that properties expose a state API, whereas fields expose a state implementation detail.
The semantics of a field and a property are identical outside the class it is defined in.
That's not true.
The difference is visible via reflection, which is often very important. For example, many binding frameworks won't use fields, only properties.
You can pass a mutable field by ref, but not a property - so changing a field to a property breaks source compatibility. (Code using SomeMethod(ref x.Products) will become invalid when Products becomes a property.)
Changing a field to a property also breaks binary compatibility, so if assembly X was built against assembly Y v1.0, and you change a field to a property for assembly Y v1.1, then you'd need to rebuild assembly X or it would fail to execute correctly
If you have a mutable value type (please don't do this) then writing foo.Location.X = 10 works when Location is a field (because x.Location is classified as a variable) whereas it doesn't when Location is a property (because then the expression x.Location is classified as a value). If you have a method (in your evil mutable type) which mutates the value instead, then foo.Location.DoSomething() will compile in both cases, but have a different effect. Fun for all the family.
Its depend on the situation. I'll prefer to use the property over the field. You have mentioned that public IEnumerable<string> Products; and public IEnumerable<string> Products { get; set; } are same, but in actual they are not. During compilation the property will get converted into two methods (i.e. get_Products() and set_Products()).
The advantage of property is to allows you to specify the custom code before assigning and returning the data, this is not possible with the field. Check the example below
public IEnumerable<string> Products
{
get
{
if(DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
{
//Return future product
return new List<string>();
}
else
{
// return current products
return new List<string>() { "testing" };
}
}
set
{
if (DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
{
//ignore assign product
Products = new List<string>();
}
else
{
// add assign product
Products = value;
}
}
}
Using the auto-property syntax is preferable because it creates a read/write property with a private backing field, thus allowing you to change the implementation (from a private scalar field to a dictionary entry or another backend with some other custom logic), thus freeing the "class's interface" (not the same thing as an interface) from its implementation.
Note that for collection member properties, it is advisable to make their setters private, like so:
public IEnumerable<String> Products { get; private set;}
...that way only the containing class can alter it.
Another alternative is the private readonly field, in C# 6 you can use auto-implemented properties with readonly backing fields like so:
public IEnumerable<String> Products { get; } = SomeSource.GetProducts();
If I put an object in the dictionary, whether it becomes a pointer?
I have the following dictionary:
public Dictionary<string, Class1> Dic{ get; set; }
In the following function I update / add to the dictionary
private void Update(string Name)
{
if (Name== null || Name=="")
return;
if (Dic.ContainsKey(Name))
{
Dic[Name] = MyClass;
}
else
{
Dic.Add(Name, MyClass);
}
}
MyClass is a variable that sitting in the same class with the dictionary
public Class1 MyClass { get; set; }
When i changed the class i call to update function, i see that all the dictionary contaion the same value: current MyClass , why?
How can I prevent this?
You are adding the same class object against multiple keys in your dictionary, but all of them are pointing to the same object that is why when you change one object, you see the changes across the dictionary. You need to make copy of your class object and then add it to the dictionary.
You may see this discussion: How do you do a deep copy an object in .Net (C# specifically)? on Stackoverflow.
Other than that, you can get rid of your check against keys, since you are checking if the key doesn't exist add, otherwise update. you can simply do:
private void Update(string Name)
{
if (Name== null || Name=="")
return;
Dic[Name] = MyClass;
}
Which would do the same (add if doesn't exist and update if exist)
Because the class you put in is by reference, so when you change it someplace, it 'changes' there, too (it doesn't really change there, it only changes in one place, but we're all looking at the same thing, so to speak). So, it's nothing really to do with the dictionary, but the mechanics of .NET.
You wouldn't see such changes reflected if you put a value type in, say an integer, then changed the variable value. You could define structures, if appropriate for your situation, which are value types, and you could 'reuse' the type without 'cascading changes'.
No. And sort-of-yes. You never "put and object in the dictionary" - you actually put a reference to an object into the dictionary. The reference points to the original object : the object is not cloned.
If Class1 was a struct, then it would indeed be copied whenever you access it or insert it.
In human terms: a reference is the written address to a house, say. Lots of people can have a copy of that address. If somebody goes to the house and paints the door red, then that is seen by everyone who looks at that address.
(I think I stole this analogy from Jon; sorry Jon)
It sounds like you are doing something like:
MyClass obj = new MyClass();
foreach(var name in names) {
obj.Update(name);
}
when you should be doing:
foreach(var name in names) {
MyClass obj = new MyClass();
obj.Update(name);
}
The distinction here is how many objects we have.
Because class is a reference type. That means every variable of that type is a pointer to that type.
Your class is a reference type, so Dictionary contains it's memory link. Actually you can check more at reference types and value types
Consider a simple class:
public class TestClass<Val>
{
public Val Value{get;set;}
}
Create an instance of this class and define a dictionary where we use it as a key.
TestClass<int> TestCase = new TestClass<int>();
Dictionary<TestClass<int>, int> D = new Dictionary<TestClass<int>, int>();
Put 0 into the TestCase and add the entry to dictionary:
TestCase.Value=0
D.Add(TestCase,10)
Now the dictionary looks like this: {TestCase -> Value=0:10}
Now do this:
TestCase.Value=1
Now I have in the dictionary {TestCase -> Value=1 : 10} automatically, without putting the key 'TestCase -> Value=1' into the dictionary. How can I avoid it?
Basically, don't use mutable types as keys... or if you do, make sure you never mutate the key. The first would be preferable.
An even bigger problem is that if TestClass<Val> has a custom GetHashCode() / Equals() implementation, you can completely break the dictionary, as it may no longer be able to find a value for that key, even if you give it the exact instance you started with.
Anything you use as a key should ideally be immutable. For that reason, int and string make great choices, but you can also just make your type immutable, as per #lazyberezovsky's example.
Create immutable TestCase class:
public class TestClass<Val>
{
public TestClass(Val value)
{
Value = value;
}
public Val Value{ get; private set; }
}
Actually there is one single instance of TestClass. You created it outside dictionary and then added that instance to dictionary.
If you make changes to instance it reflects inside dictionary. This is shallow copying
To avoid this problem create a deepclone of your instance and then add in dictionary. In that case changes in one will not be reflected in another.
I swear I have seen an example of this but have been googling for a bit and can not find it.
I have a class that has a reference to an object and need to have a GET; method for it. My problem is that I do not want anyone to be able to fiddle with it, i.e. I want them to get a read only version of it, (note I need to be able to alter it from within my class).
Thanks
No, there's no way of doing this. For instance, if you return a List<string> (and it's not immutable) then callers will be able to add entries.
The normal way round this is to return an immutable wrapper, e.g. ReadOnlyCollection<T>.
For other mutable types, you may need to clone the value before returning it.
Note that just returning an immutable interface view (e.g. returning IEnumerable<T> instead of List<T>) won't stop a caller from casting back to the mutable type and mutating.
EDIT: Note that apart from anything else, this kind of concern is one of the reasons why immutable types make it easier to reason about code :)
Return a reference to a stripped-down interface:
interface IFoo
string Bar { get; }
class ClassWithGet
public IFoo GetFoo(...);
If the object isn't too complicated/extensive then write an wrapper around it.
for example:
class A {
public string strField = 'string';
public int intField = 10;
}
class AWrapper {
private A _aObj;
public AWrapper(A aobj) {
_aObj = A;
}
public string strField {
get {
return _aObj.strField;
}
}
public int intField {
get {
return _aObj.intField;
}
}
}
So now all you do is give your client code an instance of the AWrapper class so that they may only use what you allow them to see.
this may get a bit complicated and may not scale well if your base class is not set in stone, but for most simple situation it may just do the trick. I think this is called a facade pattern(but don't quote me on that =) )
This isn't possible. Get and set accessors to reference types get and set the reference to the object. You can prevent changes to the reference by using a private (or internal) setter, but you cannot prevent changes to the object itself if it's exposed by a getter.
Your question reads like you're looking for:
public PropertyName { get; private set; }
But then, given the answers so far I'm not sure I'm interpreting your question correctly. Besides, who am I to question Jon Skeet? :)
i agree with ReadOnlyCollection
See my simple code:
private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices
{
get
{
return (_devices.AsReadOnly());
}
}
ReadOnlyCollection dosen't has Add method so user cant add properties to it.BUT ther is no warranty that if user can modify objects by calling their methods....
I have faced this problem in a certain way.
I have a CategoryViewModel class, which have a property Category that I want private read-only :
public CategoryViewModel
{
private Category { get; }
}
In fact, I want it to be exported as read-only to other class. However I can't do such thing.
In my case (maybe it will help some other guys), I want to add it to a repository. The only way that I've found is to have a function with the repository as param 1, and an Action as param 2 :
public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
{
action(repo, Category);
}
Like that, from elsewhere, I can do such thing :
categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));
This can help other to expose there property only for certains cases and can manage them.
I've got a Customer class that has a List<string> Roles property. Much of the time I want to access that property as a list of strings, but on occasion I want to see it as a comma-delimited list.
I could certainly do that in a new method, and if I anticipated wanting to get the value of the variable in different formats (comma-delimited, tab-delimited, &ct) I would certainly do so. However, I'm toying with the idea of using two different properties to access the variable value, something along the lines of
public List<string> Roles
{
get { return this._Roles; }
set { this._Roles = value; }
}
and
public string RolesToString
{
get { do some work here to comma-delimit the list; }
}
Essentially I want to override the ToString() method of this particular list. Are there compelling reasons for doing 1 over the other? Is using two different properties to return the same variable value sufficiently non-standard to cause red flags?
I would make your second "property" a method. It's doing additional processing on your list, and returning something that isn't a direct "property" of the object, but more a processed version of the object's property. This seems like a reasonable method candidate.
My preference would be:
public List<string> Roles
{
get { return this._Roles; }
set { this._Roles = value; }
}
public string GetRolesAsString()
{
// Do processing on Roles
}
As Reed says it should probably be a Method, but thats kindof subjective.
Note that you don't need much code to do it - just a call to Join()
public string RolesAsString()
{
return String.Join(", ", this._Roles);
}
And given that string joining is so easy in .NET, do you really need a method/property for it?
I have no problem with what you propose. Except I would name it RolesString.
But... Why only a getter? If I can set the Roles property, why could I not set the RolesString property?
Additional processing does not necessarily mean a method should be used.