Set method parameters as readonly - c#

how can i create a method that get's an object to read only purpose
public class Person
{
public string Name;
}
public void RunMe(Person p)
{
p.Name="XXXX";
}
var p =new Person();
p.Name="YYYY";
RunMe(p);
Console.WriteLine(p.Name);
I am getting XXXX. but i want that the person object will not change it value.

you can use interfaces to restrict the access. It is also better to pass interfaces instead of concrete objects as parameters to methods.
public interface IReadablePerson
{
string Name { get; }
}
public interface IWritablePerson
{
string Name { set; }
}
public class Person : IReadablePerson, IWritablePerson
{
public string Name { get; set; }
}
and then have a method like this
public void RunMe(IReadablePerson p)
{
p.Name = "XXXX"; //compile time error!!!
}

The way to do this is via the get and set accessors, just don't define a set:
public String Name { get; }
This will make a property that you can treat exactly like a normal field for your purposes. Underneath properties are a little more complex using methods to set a backing field which you can read about on msdn
If you need to be able to set the property just once then define the set as private and pass the parameter into the constructor:
public class Person
{
public Person(String name)
{
this.Name = name;
}
public String Name { get; private set; }
}

Classes in C# are reference types, so there's no way to do what you want to do if Person is a class.
You could make it a value type (by making it a struct) in which case, a copy of the object would be passed in, but that may take implications at some other points in your program, so be wary if you do it.

It seems that you want to somehow be able to lock the member. One option would be to make the "set" dependent on another member like this:
public class Name
{
public bool Locked { get; set; }
private string name;
public string Name
{
get { return this.name; }
set
{
if(!this.Locked)
this.name = val;
}
}
}
Edit: Alternate method for making lock permanent.
public class Person
{
private bool locked = false;
public void Lock()
{
this.locked = true;
}
public bool Locked
{
get { return this.locked; }
}
// add same Name member as above
}
Edit: Yet ANOTHER way to lock, using a key.
private object key = null;
public bool Locked
{ get { return this.key != null; } }
public void Lock(object obj)
{
if (this.key == null)
{
this.key = obj;
}
}
public void Unlock(object obj)
{
if (this.key == obj)
{
this.key = null;
}
}
You can throw an exception if you want if trying to unlock with the wrong key object.

The behaviour described after the first setting of the property is this:
private string _name;
public string Name
{
get { return _name; }
set { // no setting }
}
This is NOT A GOOD PRACTICE.
you create unexpected behaviour for properties (if this is a public class).
Any consuming assembly cannot view the body of the get and set methods would expect a set method to behave a sertain way (setting a value).
This kind of behaviour should be put in a seperate set method.
This way you can see if it changed, throw an exception if you want, or return true if it changed.
Then you can still use the property for getting the value.
private bool _locked;
public string Name { get; private set;}
public boolSetName(string value)
{
bool hasChanged = false;
if(!_locked)
{
Name = value;
_locked = true;
hasChanged = true;
}
return hasChanged
}

Related

Is there a way to set a default function for getters and setters?

I was wondering if there is a way to set a default function for a getter or a setter.
For example, let's say I have this:
public class MyClass
{
public bool IsDirty {get; private set; } = false;
private string _property;
public string Property1
{
get
{
return _property1;
}
set
{
if (value != _property1)
{
_property1 = value;
IsDirty = true;
}
}
}
}
I was wondering if there was a way to do something like this:
public class MyClass
{
public bool IsDirty {get; private set;} = false;
MyClass.defaultSet = { if (value != !_property1) { _property1 = value; IsDirty = true; } };
private string _property1;
public string Property1 { get; set; }
public string Property2 {get; set;}
public string Property3 {get; set;}
//...
}
So that I don't have to do it the first way on this big class I have (~100 properties).
You can reduce the noise by using a helper method like this
private void Set<T>(ref T field, T value)
{
if (!Equals(value, field))
{
field = value;
IsDirty = true;
}
}
Then you can write:
public string Property1
{
get => _property1;
set => Set(ref _property1, value);
}
No, this doesn't exist, for several reasons:
Not every property is going to be a string, so this would need to correctly handle integers, DateTimes, Decimal, etc
Primitive value types are bad enough, but then start throwing in things like Tuples, complex classes (where changing a class member is still get operation on the property itself!), delegates, etc
If you reference a property by it's own name, you're creating a circular reference that will cause a StackOverflowException.
Not every property is going to use the same Property name, so that part of the method is different. You'd need another keyword or argument to the set method.
You need a way to exempt the someBool / IsDirty property.

How to combine property init and set depending on access modifier?

I want a class/record with protected set and public init access restriction?
To my knowledge this even cannot be done by explicitly implementing a "Set" interface like this:
public interface ISetData<T>
{
T Value { get; set; }
}
public class Data : ISetData<bool>
{
bool ISetData<bool>.Value { get => Value; set => Value = value; } // Error The property Value has no setter
public bool Value { get; init; }
}
Downside is, set functionality is public when using the interface. Not good. (for internal components the interface can be made internal, but that's mostly no option)
Given that only derivations of Data should be able to set data after initialization, the only solution I see is to use an backing field for the property, which is annoying.
Which looks like:
public interface ISetData<T>
{
T Value { get; set; }
}
public class Data : ISetData<bool>
{
bool ISetData<bool>.Value { get => Value; set => _value = value; } // Fine
private bool _value;
public bool Value
{
get { return _value; }
init { }
}
}
That seems odd to me. Would it not be better CLR/c# allows to use access modifiers independently of set/init this like:
public class Data
{
public bool Value { get; init; protected set; }
}
I know this would better be addressed by a feature request, but this is not what this post is about.
So what solutions are available for the scenario "public init, but protected set"?
A simple answer is none.
In C# 9.0, you could have either init or protected set, not both.
You could have a separate property that is protected set and then the public property can be based on your protected property. Example below.
using System;
public class Program
{
public static void Main()
{
var example = new Example{Test = "hello world"};
example.PrintProtectedTest();
Console.WriteLine(example.Test);
example.SetProtectedTest("goodbye world");
Console.WriteLine(example.Test);
}
}
class Example
{
public Example()
{
}
protected string ProtectedTest { get; set; }
public string Test
{
get => ProtectedTest;
init => ProtectedTest = value;
}
public void SetProtectedTest(string test)
{
ProtectedTest = test;
}
public void PrintProtectedTest()
{
Console.WriteLine(ProtectedTest);
}
}
You can run the example here https://dotnetfiddle.net/odGwDj

Setter of a singleton from an custome class in .Net C# not triggered if only one property changed

I have this class
public class SPP {
static PPModel PP= null;
public PPModel sPP
{
set
{
if (PP != value)
{
PP = value;
//save PP in database
}
}
get
{
if (PP == null)
{
//lazy loading of PP
}
return PP;
}
}
}
public class PPModel
{
public string property1 { get; set; }
public int property2 { get; set; }
public int property3 { get; set; }
public int property4 { get; set; }
public Dictionary<string, int> property5 { get; set; }
}
Now if I set sPP in this way, everything works fine:
SSP.Instance.sPP = new PPModel(){...};
But I want to know if it is possible to just update one property of this singleton and trigger the setter in this way:
SSP.Instance.sPP.property4 = 7;
If I do it in this way, the singleton sPP has the updated value, but the setter seems not to be triggered what means the additional code like database save will not work.
Any chances to get this working?
Thanks in advance.
a good solution for this is to change the model to have full properties definitions, and on the setters, call the DB update, as such:
public class PPModel
{
private string _fieldOne;
public string Property1
{
get { return _fieldOne; }
set
{
_fieldOne = value;
// update DB
}
}
private int _field2;
public int Property2
{
get { return _field2; }
set
{
_field2 = value;
// update DB
}
}
// and so on for all properties
}
You can't trigger setter in your singleton by updating internal stored object properties.
You can trigger your setter like this:
SSP.Instance.sPP = new PPModel(){...};
var instance = SSP.Instance.sPP;
instance.property4 = 7
SSP.Instance = instance;
This way you'll reset the exact variable to your instance and trigger update.
But, as you're implementing singleton, it is NOT responsible for making actions related to the object it stores.
You have to monitor changes in your PPModel object, as only this class is responsible for it's internal state.

Setting only a setter property

I have an object model that has a property like this:
public class SomeModel
{
public string SomeString { get; set; }
public void DoSomeWork()
{
....
}
}
I want the DoSomeWork function to execute automatically after the SomeString property changes. I tried this but it's not working:
public string SomeString { get; set { DoSomeWork(); } }
What's the correct syntax?
Use a private field instead, like this ...
public class SomeModel
{
private string someString = "";
public string SomeString {
get { return this.someString; }
set {
this.someString = value;
this.DoSomeWork();
}
}
public void DoSomeWork()
{
....
}
}
You can't do this with automatic properties - you'll have to create a "manual" property backed by a field.
private string _someString;
public string SomeString
{
get { return _someString; }
set
{
_someString = value;
DoSomeWork();
}
}
If you really can't deal with this boilerplate (say you'd have to do this hundreds of times), consider using an AOP framework like PostSharp to implement this on your behalf - you'd just need to declare an automatic property and an attribute to get the binary rewriter to implement the desired scheme.
This will work...
private string _someString;
public string SomeString { get { return _someString; } set { _someString = value; DoSomeWork(); } }
private string _someString;
public string SomeString
{
get
{
return _someString;
}
set
{
DoSomeWork();
_someString = value;
}
}
C# team has introduced the auto-implement properties in C# 3.0. with the logic of minimizing the model making which is backed by an anonymous field created by compiler. this one is used when you don't need to implement any additional logic on a property of an object class. so it just followed as.
public string Name{ get; set;}// auto-implemented property. no additional logic.
if we want to add some logic as you want to add one function. we must be writing a manual property backed by a private field as like below.
private string _Name;
public string Name
{
get {return _Name;}
set {
_Name=value;
DoSomething(); //Additional logic implemented.
}
}

In C#, can I hide/modify accessors in subclasses?

I'm not even sure what this principle is called or how to search for it, so I sincerely apologize if it has been brought up before, but the best way to do it is with an example.
class Properties
{
public string Name { get; set; }
}
class MyClass
{
class SubProperties: Properties
{
public override Name
{
get { return GetActualName(); }
set { SetActualName(value); }
}
}
public SubProperties ClassProperties;
private string GetActualName()
{
return SomeFunction();
}
private void SetActualName(string s)
{
ClassProperties.Name = SomeOtherFunction(s);
}
}
The idea is to have any object that instantiates MyClass have a fully accessible property ClassProperties. To that object, it would look exactly like a Properties object, but behind the scenes, MyClass is actually computing and modifying the results of the fields. This method of declaration is obviously wrong since I can't access GetActualName() and SetActualName() from within the SubProperties definition. How would I achieve something like this?
Are you looking for something like this?
abstract class Properties
{
public abstract string Name { get; set; }
}
class MyClass
{
private class SubProperties : Properties
{
private MyClass myClass;
public SubProperties(MyClass myClass)
{
this.myClass = myClass;
}
public override Name
{
get { return this.myClass.GetActualName(); }
set { this.myClass.SetActualName(value); }
}
}
private string name;
public MyClass
{
this.MyClassProperties = new SubProperties(this);
}
public Properties MyClassProperties { get; private set; }
private string GetActualName()
{
return this.name;
}
private void SetActualName(string s)
{
this.name = s;
}
}
You need to pass a reference to a MyClass instance to the SubProperties instance if you want to access MyClass methods from SubProperties.
public virtual string Name { get; set; }

Categories

Resources