I'm attempting to re-write a VB.NET WebForms application in C# MVC. I'm having an issue with one of the properties when using Entity Framework to instantiate a class.
I have a column in my database "VATInclusive", which is of type 'int'. The original application implicitly converted a "1" or "0" to "true" or "false", but when trying to do this in my application, I get the following error:
The 'VATInclusive' property on 'Shop' could not be set to a
'System.Int32' value. You must set this property to a non-null value
of type 'System.Boolean'.
I can't simply change the type in the database as other applications make use of the table. I've tried using the following code to convert the value, but it seems to only return false, regardless of whether the database has a "0" or a "1"... Can anybody suggest a solution to this?
[Column("VATInclusive")]
private int _VATInclusive { get; set; }
[NotMapped]
public bool VATInclusive
{
get
{
if (_VATInclusive == 0)
{
return false;
}
else
{
return true;
}
}
set
{
if(_VATInclusive == 0)
{
this.VATInclusive = false;
}
else
{
this.VATInclusive = true;
}
}
}
Following some advice from the answers provided, I have rectified the issue. The issue lay with the setter accessor and also with the _VATIncusive property. By changing the code to the following I have managed to get the system to work as I expected.
However, I feel that this isn't the best approach, but it appears to be working correctly...
EDIT : EDIT : I've reduced the get accessor as per advice from Ryan and hvd..
EDIT : I'm not sure of the implications of having both properties set to public. But I don't think this is going to be an issue.
[Column("VATInclusive")]
public int _VATInclusive { get; set; }
[NotMapped]
public bool VATInclusive
{
get
{
return _VATInclusive != 0;
}
set
{
_VATInclusive = value ? 1 : 0;
}
}
If you store the column as a bit, Entity Framework automatically queries it as a Boolean for you.
You can't have a setter accessor assign to itself - this will always result in a StackOverflowException. In the below code:
set
{
if(_VATInclusive == 0)
{
this.VATInclusive = false;
}
else
{
this.VATInclusive = true;
}
}
every time this.VATInclusive is assigned to, the control flow returns to the beginning of the set accessor. This obviously can never complete.
You have some typos on your setter. I think you mean for it to be:
set
{
if(value == false)
{
_VATInclusive = 0;
}
else
{
_VATInclusive = 1;
}
}
Basically, "value" represents the bool value passed in to your setter (to be converted in to an integer). _VATInclusive is the actual object that you want to be modifying under-the-hood.
In your set, you need to compare against value:
if (value == 0)
Related
Read only properties can be assigned in a constructor. But when I try to explicitly implement get method, compiler shows an error (Property cannot be assigned to -- it is read only.) Can I implement getter or it's supposed to be without implementation?
public class PersonalIncome
{
private decimal _anualRate;
public decimal AnualRate
{
get { return _anualRate != 0 ? _anualRate : 40_000; }
}
public PersonalIncome(decimal paymentRate)
{
switch (paymentRate)
{
case var rate when (rate > 300):
AnualRate = rate; // **Property can not be assigned to -- it is read only.**
break;
default:
break;
}
}
}
You can implement the getter, but then you can only assign values to the backing field directly:
_anualRate = rate;
Once you decide against using the convenience of the auto-property, you have to do everything by yourself.
Your class could be rewritten like this:
public class PersonalIncome
{
public decimal AnualRate { get; private set; }
public PersonalIncome(decimal paymentRate)
{
AnualRate = paymentRate > 300 ? paymentRate : 40_000;
}
}
You refer to a property with a readonly backing-field.
That´s exactly what the compiler also generates from C#6 upwards when using an auto-implemented property with a default-value:
int MyProperty { get; } = -1;
This will be translated to the following:
readonly int _myProperty = -1;
int MyProperty { get { return this._myProperty; } }
Now the compiler replaces every call to your property by the backing-field. However this only works for auto-properties that do not have a body defined. In your case you already have one, which is why the compiler can´t replace that one. As a property itself is nothing but a get- and a set-method, what you want to do is the following, which is obvious non-sense:
int get_MyProperty() { return this._MyProperty; }
...
this.get_MyProperty() = 1;
The reason this works for an auto-property is that the compiler knows how to replace the call to the property. However suppose your own getter was more complex:
get
{
DoSomething();
return this._myProperty + 5;
}
Now the compiler can´t replace the call to the property.
So the only way to have your own get-implementation tigether with a property which is get-only, is to use the backing-field:
this._myProperty = 1;
Is there any way to fast override the "value" name for a new variable that is placed in the set block in C#?
class Foo {
string name = "guy";
public string Name {
get {
return name;
}
set {
if (value != "foo") {
name = value;
} else {
Console.WriteLine("sorry I already took that one!");
}
}
}
For example in swift I could write it this way:
var Name: String {
get {
return name;
}
set (newName) {
if (newName == "Foo") {
print("sorry I already took that one!")
} else {
name = newName;
}
}
}
I know I can easily solve it by assignment at the beginning of the block but the approach with naming the value in parenthesis just after the keyword is very clear to me so just wanted to ask is there another solution.
Basically, no. It is a language feature that value is the contextual keyword that always represents the incoming value in a set accessor (and in custom event accessors).
You can fake it:
var newName = value;
but... you get better syntax highlighting with value than newName, and any C# reader automatically knows what value represents in that context.
My lecturer told us to use private fields and public properties. Recently, I was watching a tutorial video. The presenter only created properties. Is it ok to just use the property?
Public properties such as
public string Name { get; set; }
automatically implement private backing fields by the compiler. You never see them, but the effect is the same as manually specified backing fields.
private string name;
public string Name { get { return name; } set { name =value; } }
For .Net framework 2.0 and less, private fields are necessary, otherwise you will get compile errors.
In higher versions of .Net Framework, it will work fine without any errors.
Using private fields has many advantages
Validating the inputs before assigning them to the properties
public int Max
{
get { return m_Max; }
set
{
if (value>0 && value<100)
{
m_Max=value;
}
}
}
Triggering exceptions for incorrect values
From https://msdn.microsoft.com/en-us/library/ms229006.aspx,
preserve the previous value if a property setter throws an exception.
AVOID throwing exceptions from property getters. If a getter can throw
an exception, it should probably be redesigned to be a method
public int Max
{
get { return m_Max; }
set {
if(value > 0 && value < 100){ \\Value is within valid range
m_Max = value;
}
else if(value < 0)
//throw some exception to indicate value is not valid
else if(value > 100)
//throw some exception to indicate value is not valid
}
}
Yes it's okay to use public properties without private fields, though just using public fields is not okay. The reason for this is with properties you have the ability to change how you validate and store the field internally later on, whereas with just public fields changing would break any users of your class. The key difference is that with properties you still have control of the internal state of the class, even if that's with auto generated fields, whereas with public fields you don't.
In C# I'm writing a class that checks the values of its properties with a setter method:
private int _grade
public int Grade {
get { return _grade;}
set { if (value >= this.lowerLimit) _grade = value; }
}
I would like to signal to the application if a value was rejected. I had considered refactoring to use a setGrade function that returns a bool (accepted / rejected) but the ability to do someInstance.Grade++ and someInstance.Grade*=2 are important. Simple functions incrementGrade and divideGrade will make the code a mess, and there will certainly be some function that I forgot to implement (too much coupling).
My current solution is to check the value of someInstance.Grade after setting it, to ensure that it has been set. But it seems to me that this is just moving the mess from the class to the application. Indeed, it is the responsibility of the application to ensure that the value was properly set.
How do those more experienced handle this? Thanks!
It is indeed caller's responsibility to set values that make sense.
Normally, it is accepted practice to throw ArgumentOutOfRangeException in the setter when the value is wrong. If the caller expects possibly wrong value (e.g. user input), it can catch the right exception.
private int _grade
public int Grade {
get { return _grade;}
set {
if (value < lowerLimit) {
throw new ArgumentOutOfRangeException("value",
string.Format("Grade must be higher than or equal to {0}.", lowerLimit)
);
}
_grade = value; // will not happen if the exception was thrown
}
}
There is also ArgumentNullException for null values when you don't want them, and general ArgumentException if your argument rejection reason is different from these two cases.
A more hip approach would be to use Code Contracts as suggested by Jean-Bernard.
However this feature is still somewhat new and not widely used in .NET projects.
Code Contracts add static analysis so you discover such errors at compilation stage.
They will still throw ArgumentExceptions in runtime, though.
You could use Code Contracts
Here is an answer to another question which has more resources: link
Most of the time, I either silently adjust the value given to be within the range of values, or throw an Exception, depending on the situation.
Another option: you could make an event PropertyValueRejected that your class's clients could subscribe to:
public class PropertyValueRejectedEventArgs {
public string PropertyName { get; set; }
public object RejectedValue { get; set; }
}
public class MyClass {
public event EventHandler<PropertyValueRejectedEventArgs> PropertyRejected;
private int _grade = -1;
public int Grade {
get { return _grade; }
set {
if (value >= this.lowerLimit) {
_grade = value;
}
else if (PropertyRejected != null) {
PropertyRejected(
this,
new PropertyValueRejectedEventArgs {
PropertyName = "Grade",
RejectedValue = value
}
);
}
}
}
}
public int IndicationCalculatorGroupId { get; set; }
When I have it like that, it works.
public int IndicationCalculatorGroupId
{
get
{
return IndicationCalculatorGroupId;
}
set
{
IndicationCalculatorGroupId = value;
SelectList tempList = Chatham.Web.Models.Shared.DropDownData.IndicationsGroup(SessionManager.Company.EntityID, ICConstants.IndicationsCalculatorGroupType);
foreach (SelectListItem item in tempList)
{
if (value.ToString() == item.Value)
{
GroupDisplayName = item.Text;
break;
}
}
}
}
That however doesn't seem to work. Basically, I wanted to customize the setter so that when it was set, it would use the value to set it, along with searching for the value in a SelectList to set another property with another value.
Am I doing this right?
If you want custom getter/setter you must create underlying field. Otherwise calls to IndicationCalculatorGroupId inside getter will produce StackOverflow.