Using c# auto-implemented properties can I have a class that does the following (psuedo C# code because I get an error - which is below when trying to compile this):
public class Foo {
public String HouseName { get; private set; }
public int HouseId { get; private set; }
public int BedsTotal {
get { return (BedsTotal < 0) ? 0 : BedsTotal; }
private set;
}
}
Error 5 'House.BedsTotal.set' must declare a body because it is not marked abstract, extern, or partial c:\src\House.cs
To me it seems like I should be able to get a body for the getter and rely on the private set being auto-generated like it would be if I did a { get; private set; } but that's not working.
Do I need to go the whole way and set up member variables, take the private setter off, and use the members vars instead?
Thanks!
Yes, you'll need to set up private variables because at the moment you will end up in a loop trying to read the get {} portion because it references itself.
Set up a private backing variable like this:
private int _bedsTotal;
public int BedsTotal {
get { return (_bedsTotal < 0) ? 0 : _bedsTotal; }
private set { _bedsTotal = value; }
}
Then you can access beds through the private setter
i whould go for an even more easier approach
private int _bedsTotal;
public int BedsTotal
{
get
{
return (this._bedsTotal < 0) ? 0 : this._bedsTotal;
}
private set
{
this._bedsTotal = value;
}
}
and so you can set the value of BedsTotal like this : this.BedsTotal = [integer];, no need to used other private methods since you can make use of the set
Related
I am not sure this is syntactically possible. If I have duplicate logic that would go in a getter/setter. Is there a way for a variable to inherit that pattern instead of re-typing the code.
private int basicVar;
public int BasicVar
{
get { return basicVar; }
set
{
if (IsServer)
{
basicVar = value;
Debug.Log("The variable name is: " + nameof(BasicVar));
//Other code
}
}
}
private int turn
public int Turn
{
//Inherits from basicVar
}
I am not sure if such a thing is possible, I was just curious.
(If it is, how could I template the private variable?)
I could do this by making it its own class, but I would prefer to keep it a primitive.
As mentioned in the comments, when needing to build reusable behavior, the preferred approach is to encapsulate the behavior in functions that can be called instead of the getter/setter of the property itself. This allows you to clearly define your expected behavior and allows you to easily compose logic by calling other methods.
public class Test
{
public bool IsServer { get; set; }
public int BasicVar { get; set }
public int Turn { get; set; }
public void UpdateBasicVar(int updatedValue)
{
if (IsServer)
{
BasicVar = updatedValue;
Debug.Log("The variable name is: " + nameof(BasicVar));
//Other code
}
}
public void UpdateTurnAndBasicVar(int updatedValue)
{
Turn = updatedValue;
Debug.Log("The variable name is: " + nameof(Turn));
UpdateBasicVar(updatedValue);
}
}
This also helps prevent side effects in your code. Typically, when using properties, C# developers expect that interacting with that property ONLY affects that property. It is not expected that updating one property would also update another.
Consider the following example:
public class SideEffects
{
private int basicVar;
public int BasicVar
{
get { return basicVar; }
set
{
if (IsServer)
{
basicVar = value;
Debug.Log("The variable name is: " + nameof(BasicVar));
//Other code
}
}
}
private int turn;
public int Turn
{
get { return turn; }
set
{
turn = value;
BasicVar = value;
}
}
}
while this is essentially functionally equivalent to the previous method-based example, it is no longer self-documenting. There is no way to determine from the public contract of the class that updating Turn will also update BasicVar, which is considered a side effect.
I am using a get set method to loop another method. As shown below, I am trying to increase the value of Table10_3 in the ValuesForTableLooping class. In the Main method, I have called the get set property to increase the value by one.
I have 2 questions at hand,
Is there a way to call the get set method without putting it as Inc.Val = 0;?
Why does changing any value in Inc.Val = 0; not affect the outcome?
class Class2
{
public class ValuesForTableLooping
{
public static int Table10_3 = 1;
}
public static void Main()
{
Console.WriteLine(ValuesForTableLooping.Table10_3);
Increase Inc = new Increase();
Inc.Val = 0;
Console.WriteLine(ValuesForTableLooping.Table10_3);
Inc.Val = 0;
Console.WriteLine(ValuesForTableLooping.Table10_3);
Inc.Val = 0;
Console.WriteLine(ValuesForTableLooping.Table10_3);
}
public class Increase
{
private int val;
public int Val
{
get { return val; }
set { val = ValuesForTableLooping.Table10_3++; }
}
}
}
Thank you so much once again!
Your design is pretty strange and you seem to have a great misunderstanding on what properties are.
A property is nothing - as you noticed - as a get- and a set-method. So you could achieve the exact same with the following code:
public int get_Val() { return val; }
public void set_Val(int value) { val = ValuesForTableLooping.Table10_3++; }
And here is the weird thing. A setter expects a new value for your property, which is provided as value. However you don´t use that value at all in your implementation. Instead you just increase val by one, which I would call a really strange design. You either want to set the new value from the outside with this:
public void set_Val(int value) { val = value; }
or in the property-notation:
public int Val {
get { return val; }
set { val = value; }
}
which can be further simplified by using an auto-implemented property:
public int Val { get; set; }
Another - IMHO better - way is to omit the setter completely and create some IncreaseVal-method instead:
public void IncreaseVal() { ValuesForTableLooping.Table10_3++; }
Last but not least Increase is a very bad name for a class. It does not describe a thing, but something you can do with a thing.
Is there a way to conduct error range checking in C# for class members, without Private members?
1)
For example here, I Need Private member for (less than/greater than checking).
public class PageModel
{
private int page;
public int Page
{
get => page;
set
{
if (value < 0) { page = 0; }
else page = value;
}
}
2)
If only have Public member, the get=> Page line gives SonarQube error
Add a way to break out of this property accessor's recursion
public class PageModel
{
public int Page
{
get => Page;
set
{
if (value < 0) { Page = 0; }
else Page = value;
}
}
Just curious if there is way to conduct data validation without private member. Are data annotations good method also? are they as safe as private members?
Question answered before OP's edit
Property is not a field, it is just shorthand for:
private int <>_page;
public get_Page()
{
return <>_page;
}
public set_Page(int value)
{
<>_page = value;
}
So setting Page like that doesn't make any sense.
public int Page
{
get => Page;
}
Answering your question, no, there is no way to get rid of additional field, because there is nothing to write to if you get rid of the field.
You would have to create a method such as
public int Page { get; set; }
public void Validate()
{
if(Page < 0)
Page = 0;
}
But there are endless possibilities of doing it.
Is there an access modifier, or combination thereof, to restrict access to an outer class only?
For the Position property of nested class PanelFragment below, I would like only the containing class ViewPagerPanels to be able to set it (via the setter, I realize this could be done through a constructor parameter also).
public class ParcelView : MXActivityView<ParcelVM>, ViewPager.IOnPageChangeListener, IFragmentToViewPagerEvent
{
private ViewPagerPanels _pagerPanels;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
_pagerPanels = new ViewPagerPanels(5); // 5: magic number, put int constant
_pagerPanels[0] = new ViewPagerPanels.PanelFragment(typeof(ViewA));
// ...
}
private class ViewPagerPanels
{
public class PanelFragment
{
public Fragment Fragment { get; set; }
// ?? - access modifer for set
public int Position { get; private set; }
}
public readonly int PANEL_COUNT;
private PanelFragment[] _panels;
public ViewPagerPanels(int count)
{
PANEL_COUNT = count;
_panels = new PanelFragment[PANEL_COUNT];
}
public PanelFragment this[int i]
{
get
{
return _panels[i];
}
set
{
_panels[i] = value;
// !! - cannot access private property
_panels[i].Position = i;
}
}
}
}
No, it's not possible to do it directly. The most restrictive access modifier, private, already allows access from within the same class. Every other modifier further expands that access.
Every class, no matter if its nested, private or public, always has access to every single of its own declared members, with no chance of applyng restrictions to itself. The closest we can get is by using a readonly field (or a getter only property) that prevents the declaring class from modifying a variable outside the constructor. But for a read-write one, we're out of options.
There is a solution for this type of protection scenarios. But you should do the following changes;
1- Replace you concrete class with an interface or abstract class and expose this to outside world
2- Implement this interface with a concrete class
3- Control the creation of this class by a factory method
4- Set the property by casting the interface (or abstract class) to your private class type
Sample code changes
public interface IPanelFragment
{
Fragment Fragment { get; set; }
// ?? - access modifer for set
int Position { get; }
}
class PanelFragment : IPanelFragment
{
public Fragment Fragment { get; set; }
// ?? - access modifer for set
public int Position { get; set; }
}
private IPanelFragment[] _panels;
public IPanelFragment CreateFragment(Fragment fragment, int pos)
{
return new PanelFragment() { Fragment= fragment, Position = pos };
}
public IPanelFragment this[int i]
{
get
{
return _panels[i];
}
set
{
_panels[i] = value;
// !! - cannot access private property
((PanelFragment)_panels[i]).Position = i;
}
}
A possible workaround
public int Position { get; private set; }
public int InitPosition { set { Position = value; } }
or, depending on your philosophical perspective concerning getter-less Properties
public void InitPosition(int value) { Position = value; }
Do these statements mean the same thing?
int x { get; }
readonly int x;
In answer to your question: There is a difference between readonly and {get; }:
In int x { get; } (which won't compile as there's no way to set x - I think you needed public int x { get; private set; } ) your code can keep changing x
In readonly int x;, x is initialised either in a constructor or inline and then can never change.
readonly int x; declares a readonly field on a class. This field can only be assigned in a constructor and it's value can't change for the lifetime of the class.
int x { get; } declares a readonly auto-implemented property and is, in this form, invalid (because you'd have no way whatsoever to set the value). A normal readonly property does not guarantee to return the same value every time it is called. The value can change throughout the lifetime of the class. For example:
public int RandomNumber
{
get { return new Random().Next(100); }
}
This will return a different number everytime you call it. (Yes, this is a terrible abuse of properties).
No, the statements do not mean the same thing. The full version of the property will have a backing variable:
private int _x;
public int X
{
get { return _x; }
}
Another method in the class could modify the backing variable, changing the value of the property:
private void SomeMethod(int someValue)
{
_x = someValue * 5;
}
The readonly keyword only allows a member variable to be assigned in its declaration or in the constructor:
// Both of these compile
private readonly int _x = 1;
public SomeClass()
{
_x = 5;
}
// This will not compile
private void SomeMethod(int someValue)
{
_x = someValue * 5;
}
So a get-only property whose backing variable is marked readonly is a true read-only property.
Other answers are sorta outdated…
In newer versions of C# you can assign a default value to int x { get; } = 33; which changes things.
Basically, it gets compiled down to get-only property with a readonly private backing field. (See https://softwareengineering.stackexchange.com/q/372462/81745 for more details)
Another difference I see is that you can't use the readonly version when using interfaces as you can only define methods and properties.
readonly keyword is making sure that these variables dont change once initialised // it is equalant to making a variable private and setting getter for it.
Example.
public class PlayerAuthData
{
public readonly string emailId, password, userName;
private string hello;
public PlayerAuthData(string emailId, string password, string userName)
{
this.emailId = emailId;
this.password = password;
this.userName = userName;
}
public string Hello
{
get { return hello; }
set { hello = value; }
}
}
public class AuthManager
{
void Start()
{
PlayerAuthData pad = new PlayerAuthData("a#a.com", "123123", "Mr.A");
pad.Hello = "Hi there";
print(pad.Hello);
print(pad.password);
print(pad.emailId);
print(pad.userName);
}
}
Literally, there's no big difference because you've declared x to be private (the default). You can always re-compile your class to make x different.
However, if it were public, the definition public int x { get; } allows you to later expand the definition to something like this:
int x { get {
return DoSomeOperation();
}
}
You can do that without breaking your clients. The implementation of the getter is private and clients call it without knowing if it is a static value or has an operation inside its get accessor.
Propery can have backing variable that can be set using any method of that class
private int a;
public int A{get;}
public void ChangeAMethod(int value){
a=value;
}
However readonly fields can only be assigend in constructor or in-line.