I want to create a variable (int) read-only in the Property Grid.
There is something I do not understand.
The variable is without set, why it still allows me to change the value (and fall when it fails to put the value into the variable)?
private int _myVar= 1;
public int MyVar
{
get { return _myVar; }
}
Try the ReadOnlyAttribute:
private int _myVar= 1;
[ReadOnly(true)]
public int MyVar {
get { return _myVar; }
}
Related
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.
i.e.
MyClass myClass = new MyClass() { Value = 5 };
I have a bunch of constructor calls like the one above, but now I've realized I need to add logic to the constructor, which was a massive oversight. Currently I have no constructor, so just a blank implicit default constructor.
The below code should explain my problem.
Edit: I'm not actually doing validation, that's just a simple example of constructor logic
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Test(1) + " should be true");
Console.WriteLine(new Test(0) + " should be false");
Test test = new Test(0) { Value = 1 }; // It allows this syntax, oddly, but the value that's used is the one passed as a parameter
Console.WriteLine("I wish " + test + " was true");
// This is what I have currently, but I'd like to add logic like that which exists in the parameterized constructor
//Test test = new Test() { Value = 1 } // Would ideally function just like Test(1), otherwise I have to go and change every call
// OUTPUT
// True should be true
// False should be false
// I wish False was true
Console.ReadLine();
}
}
class Test
{
public bool? IsGood { get; }
public int Value { get; set; }
// This doesn't currently exist in my class, but I'd like to add it
public Test(int value)
{
if (value == 1)
IsGood = true;
else
IsGood = false;
}
public override string ToString()
{
return IsGood.ToString();
}
}
Don't write code like this in the first place.
I'd write your code like this:
class Test
{
public static bool IsValid(int value)
{
return whatever; // test for validity here
}
public int Value { get; private set; } // Don't let anyone change it.
public Test(int value) {
if (!IsValid(value)) throw new InvalidArgumentException("value");
this.Value = value;
}
}
There, now Value is always valid; the user can know ahead of time whether it is valid or not; an attempt to set an invalid value produces an exception. This assumes that Value cannot change.
If Value can change then write it like this:
class Test
{
public static bool IsValid(int value)
{
return whatever; // test for validity here
}
private int value;
public int Value { get { return value; }
set
{
if (!IsValid(value)) throw new InvalidArgumentException("value");
this.value = value;
}
}
public Test(int value) {
this.Value = value;
}
}
Now the value is again always legal.
If it is legal for value to be invalid, then:
class Test
{
public bool IsValid
{
get
{
return whatever; // test for validity here
} // read-only property
}
public int Value { get; set; }
public Test(int value) {
this.Value = value;
}
}
Now the value can be any integer and whether it is valid or not can be tested dynamically.
Can I set members outside of a constructor while still using logic in the constructor?
Meaning, what, exactly?
Using the object initializer syntax, a constructor still runs. You may even choose which one to use, through the normal constructor overload syntax (which you seem to show, but you say it's not in your class?). The code in your constructor looks at the parameter value that is passed to it, not the property Value (which it doesn't even set). But if you meant for the two to work together, then sure…you can set the property in the constructor and set IsGood in the Value property setter.
If you're going to do it that way, then I would not bother with the logic in the constructor at all. Just set the Value property and let its setter do the rest of the work:
class Test
{
public bool? IsGood { get; private set; }
private int _value;
public int Value
{
get { return _value; }
set
{
_value = value;
IsGood = _value == 1;
}
}
public Test(int value)
{
Value = value;
}
}
I should point out that the semantics of the above is slightly different from what you seem to have started with. That is, the Value property is not read-only, and so can be set at any time. So, similarly, the IsGood property can change at any time. You previously had declared it as read-only and it was settable only in the constructor.
It's not clear from your question whether that's a problem or not. If you want IsGood to be strictly read-only (i.e. without even a private setter), then it won't be possible to do literally what you're asking for, because in the object initializer syntax, it relies on setting member properties after the constructor has already returned.
For the moment, I'll assume it's not a problem to add the private setter to the IsGood property.
Note that since IsGood apparently depends solely on the value of Value, you could even implement the above like this:
class Test
{
public bool? IsGood => _value != null ? _value == 1 : (bool?)null;
private int? _value;
public int Value
{
get { return _value ?? 0; }
set { _value = value; }
}
public Test(int value)
{
Value = value;
}
}
That is, don't even bother storing a value for IsGood. Just return the appropriate value based on the current state of the Value property (null if it's never been set, true if it's currently set to 1, and false otherwise).
namespace tutor4
{
class Class1
{
int _num = 2;
public int num
{
get
{
return _num;
}
set
{
_num = num;
}
}
public void incrementFunction()
{
num++;
Console.WriteLine("The value of _num is "+ num);
}
}
}
namespace tutor4
{
class Program
{
static void Main(string[] args)
{
Class1 class1Obj = new Class1();
for(int i=0;i<7;i++)
class1Obj.incrementFunction();
}
}
I don't know why _num does not increase, can anyone explain please?
Your setter for num property is wrong.
It should not be
set
{
_num = num;
}
because in this case it does nothing (sets _num back to its value since getter for num returns _num so this line is equivalent to _num = _num)
It should be
set
{
_num = value;
}
MSDN explanation about value keyword:
The contextual keyword value is used in the set accessor in ordinary
property declarations. It is similar to an input parameter on a
method. The word value references the value that client code is
attempting to assign to the property
Also note: your num property is just simple wrapper of _num field of class. If you don't need some complex logic in getter and setter for this property - you can change it to auto-implemented property like this:
class Class1
{
public int num { get; set;}
public Class1
{
num = 2;
}
}
Until C# version 6 you should assign default value to auto-implemented property in class constructor.
In C# version 6 (not yet released, should be available this summer) you will be able to assign default value to auto-implemented property in declaration:
public int num { get; set;} = 2;
This question already has answers here:
Overloading getter and setter causes a stack overflow in C# [duplicate]
(4 answers)
Closed 3 years ago.
class Program
{
static void Main(string[] args)
{
something s = new something();
s.DoIt(10);
Console.Write(s.testCount);
}
}
class something
{
public int testCount
{
get { return testCount; }
set { testCount = value + 13; }
}
public void DoIt(int val)
{
testCount = val;
}
}
Is what I have, because I was wanting to test and play around with the getters/setters stuff for C#. However, I get a StackOverFlowException was unhandled at "set { testCount = value + 13}". And I can't step through it, as I get a "The debugger cannot continue running the process. Process was terminated" message from Visual Studio. Any ideas what I'm doing wrong?
Edit: Today I've learned that I've done a pretty stupid derp. Given the multitudes of instant responses. Now I know better.
You have an infinite recursion, as you are referring to the property in the property.
You should use a backing field for this:
private int testCount;
public int TestCount
{
get { return testCount; }
set { testCount = value + 13; }
}
Note the property name TestCount (which also conforms to C# naming standard), as opposed to the field name testCount (lowercase t).
You should declare a variable to back the property:
class something
{
private int _testCount;
public int testCount
{
get { return _testCount; }
set { _testCount = value + 13; }
}
...
You have a circular reference in your property's getter. Try this:
class Something
{
private int _testCount;
public int TestCount
{
get { return _testCount; }
set { _testCount = value; }
}
public void DoIt(int val)
{
_testCount = val;
}
}
This:
public int testCount
{
get { return testCount; }
it returns itself, which causes it to execute itself.
Instead of return the own property in itself, store the intended value in another (preferably protected or private) variable. Then manipulate that variable both in the setter and in the getter.
class Program
{
static void Main(string[] args)
{
something s = new something();
s.DoIt(10);
Console.Write(s.testCount);
}
}
class something
{
private int _testCount;
public int testCount
{
// you are calling the property within the property which would be why you have a stack overflow.
get { return _testCount; }
set { _testCount = value + 13; }
}
public void DoIt(int val)
{
testCount = val;
}
}
What is value keyword here and how is it assigning the value to _num? I'm pretty confused, please give the description for the following code.
private int _num;
public int num
{
get
{
return _num;
}
set
{
_num=value;
}
}
public void button1_click(object sender,EventArgs e)
{
num = numericupdown.Value;
}
In the context of a property setter, the value keyword represents the value being assigned to the property. It's actually an implicit parameter of the set accessor, as if it was declared like this:
private int _num
public int num
{
get
{
return _num;
}
set(int value)
{
_num=value;
}
}
Property accessors are actually methods equivalent to those:
public int get_num()
{
return _num;
}
public void set_num(int value)
{
_num = value;
}
The value keyword is a contextual keyword, that is, it has a different meaning based on its context.
Inside a set block, it simply means the value that the programmer has set it to. For instance,
className.num = 5;
In this case, value would be equal to 5 inside of the set block. So you could write:
set
{
int temp = value; //temp = 5
if (temp == 5) //true
{
//do stuff
}
_num = value;
}
Outside of a set block, you can use value as a variable identifier, as such:
int value = 5;
Note that you cannot do this inside a set block.
Side note: You should capitalize the property num to Num; this is a common convention that makes it easier for someone who's reading your class to identify public and private properties.
Properties are the way you can READ, WRITE or COMPUTE values of a private field or class variable.
The set or setter inside a property is used when the code assigns a value into the private field or (class) variable.
The value keyword means simply "the thing that is being assigned".
public class StaffMember
{
private int ageValue;
public int Age
{
set
{
if ( (value > 0) && (value < 120) )
{ this.ageValue = value; }
}
get {
return this.ageValue;
}
}
}
//Rob Miles - C# Programming Yellow Book