So basically I've come across some readonly properties on this one class that the writer of the class told me I could make settable for a specific task. Problem is, they get their value through manipulation most of the time, not directly from a private variable in the class.
Example:
public decimal? AccruedInterest
{
get
{
if (this.Result != null)
{
return this.GetExchangedCurrencyValue(this.Result.AccruedInterest.GetValueOrDefault(decimal.Zero));
}
return null;
}
}
So if I want to add a setter, I don't want to worry about setting that Result object because I'm not sure if on it's way back out it's going to be drawn correctly.
Would I be able to do something like this?
private decimal? _AccruedInterest;
public decimal? AccruedInterest
{
get
{
if (this._AccruedInterest.HasValue)
{
return this._AccruedInterest.Value;
}
if (this.Result != null)
{
return this.GetExchangedCurrencyValue(this.Result.AccruedInterest.GetValueOrDefault(decimal.Zero));
}
return null;
}
set
{
this._AccruedInterest = value;
}
}
Or do any of you see issues that could arise from this (besides the fact that it's now changeable)?
Well your only problem with this is if they set the value to be null and you want your property to return null rather than evaluate the if statement.
But you might not allow them to set null, in which case you should add a check in the setter.
set
{
if (value == null)
throw new NullArgumentException("AccruedInterest");
this._AccruedInterest = value;
}
If it is valid for them to set null, you probably need another boolean flag to tell if the value has been set.
private bool _accruedInterestSet;
private decimal? _accruedInterest;
public decimal? AccruedInterest
{
get
{
if (this._accruedInterestSet)
{
return this._accruedInterest; //don't return .Value in case they set null
}
if (this.Result != null)
{
return this.GetExchangedCurrencyValue(this.Result.AccruedInterest.GetValueOrDefault(decimal.Zero)) ;
}
return null;
}
set
{
this._accruedInterestSet = true;
this._AccruedInterest = value;
}
}
I don't know how it's supposed to work, but syntactically I don't see anything wrong with your code.
Related
I have a c# class with many variables, all initialized to null. When first accessed, I want to compute their value and return that (storing it to speed up future accesses). To do so, I've written code like
private T nullCheck<T>(T value, string how_to_compute) {
if (value == null) {
return compute(how_to_compute);
}
return value;
}
private string _variable1
public string variable1 {
get { _variable1 = nullCheck(_variable1, "someData"); return _variable1; }
set { _variable1 = value; }
}
...
With each variable having similar code to variable1
Is there some better way to do this? Like a custom annotation that automatically creates these near-identical getters and setters?
I'd suggest doing something like this:
public string variable1
{
get { _variable1 = _variable1 ?? compute("some_data"); return _variable1; }
set { _variable1 = value; }
}
I'm using lazy load for "relationship" properties and struggling when saving object because when I check to see if everything is OK before saving, the properties I'm checking get loaded from the db, losing the object's "saving" status.
Consider this pseudo-code:
public class Project
{
private int _ProjectId;
private string _ProjectName;
private ProjectType _ProjectType;
public int ProjectId
{
get { return _ProjectId; }
set { _ProjectId = value; }
}
public string ProjectName
{
get { return _ProjectName; }
set { _ProjectName = value; }
}
public ProjectType ProjectType
{
get
{
if (_ProjectId != 0 && _ProjectType == null)
{
... load _Projectype from db here
}
return _ProjectType;
}
set
{
_ProjectType = value;
}
}
public Project Save()
{
if(this.ProjectType != null) // <<-- if the _projectId is != 0 (typically during updates or delete operations, the prop is loaded from the db!!!
adpt.Save(this);
}
}
When the control is inside the class, I can of course reference the private member to avoid dynamic loading, but what if someone use the object from the outside? A simple test "if(Prj.ProjectType != null)" will inadvertently load the property.
It seems I need a state to inhibit the loading during saving operation and I was wondering if there is a pattern out there to help me.
Many thanks, Antonio
I have a POCO that can't have any nullable properties, for various reasons, but the database I'm connecting to has null values for some of these corresponding properties, so I have to handle these and set them to something else in the property getter/setter logic. But I'm still getting...
Constraint Exception was unhandled by user code: The 'DischargeDate' property on 'Visits' could not be set to a 'null' value. You must set this property to a non-null value of type 'System.DateTime'.
...Here's my property logic....
public class Visits
{
private DateTime _dischargeDate;
public DateTime DischargeDate
{
get {
if (this._dischargeDate == null)
{
this._dischargeDate = DateTime.MinValue;
return this._dischargeDate;
}
else
{
return this._dischargeDate;
}
}
set
{
if (value == null)
{
this._dischargeDate = DateTime.MinValue;
}
else
{
this._dischargeDate = value;
}
}
}
...and the DbContext is just straight forward, like...
public class MyDBContext : DbContext
{
public MyDBContext(string connection)
: base(connection)
{
}
public DbSet<Visits> Visits { get; set; }
}
I have no idea why I'm getting this error. It throws when the context is loaded. Or to be more specific, when I try to access the DbSet<Visit> Visits, like _dbcontext.Visits;
DateTime can't be null. So even though your setter is checking for null (which I'm surprised that comparison even passes), a property of DateTime cannot be set to null. So that's why EF is throwing that error and thus that logic won't work.
If the database is going to have nulls in it, you need your POCOs to have DateTime? as their property type so that EF can set it to null.
Simply doing:
public class Visits
{
private DateTime _dischargeDate;
public DateTime? DischargeDate
{
get {
return _dischargeDate;
}
set
{
if (value == null)
{
this._dischargeDate = DateTime.MinValue;
}
else
{
this._dischargeDate = value.Value;
}
}
}
}
would work - _dischargeDate would never be null
I have the following, I want to move the setting of webDB and item outside of the following public string method which is an example how would I go about doing this.
public string Width
{
get
{
if (webDB != null)
{
webDB = Sitecore.Configuration.Factory.GetDatabase("web");
Sitecore.Data.Items.Item item = webDB.Items[StartItem];
if (item != null)
{
Sitecore.Data.Fields.Field field = item.Parent.Fields["Identity_Page_Width"];
if (!String.IsNullOrEmpty(field.Value))
{
return field.Value;
}
else
{
return "964"; // returns default pixel width if Identity_Page_Width is not defined, or is null
}
}
else
{
return "964"; // If item is not found return default width.
}
}
else
{
return "964";
}
}
}
This is how I have attempted to separate it:
public void GetConfiguration()
{
if (webDB != null)
{
webDB = Sitecore.Configuration.Factory.GetDatabase("web");
if (item != null)
{
item = webDB.Items[StartItem];
}
}
}
but I get stuck with trying to run the method within the code I get method must have a return type.
I then want to run this GetConfiguration only ONCE within the class somewhere so all methods don't need to contact the database and items data more then they have to.
I could do MyClass class = New MyClass; Class.GetConfiguration(); but I don't want future coders to have to know this needs to be instantiated every time to continue. I would rather remove that dependency.
If webDB being instantiated is critical for most/all functionality of the class, consider initializing it in the instance constructor (if non-static), or a static constructor (if static)
Otherwise, I would create a
private InitializeWebDB(){if(webDB == null){...}}
which you can call within your class when needed.
Further, on properties which require access to this, I would use methods instead such as:
public String GetWidth(){InitializeDB(); ...}
which implies more logic/overhead than a simple property field return.
Your code can be improved in a few ways. But to answer your question -
Why not use a static c'tor? This way you ensure it only runs once
public class SomeClass
{
static SomeClass()
{
if (webDB != null)
// etc. etc.
}
... // other code
}
Making the webDB variable static would impose that it will only be null in your first Property call.
private static <whatevertype> webDB;
private static <whatevertype> item;
public void GetConfiguration()
{
if (webDB == null)
{
webDB = Sitecore.Configuration.Factory.GetDatabase("web");
if (item != null)
item = webDB.Items[StartItem];
}
}
I always see properties using a private variable to hold the value like this.
private int _myValue;
public int MyValue { get { return _myValue; } set { _myValue = value; } }
Why can't I just skip the private variable and do this...
public int MyValue { get { return MyValue; } set { MyValue = value; } }
*Note: I didn't want to use auto properties because I was hoping to be able to do something like this.
public int MyValue { get { return MyValue.Tolower().Trim(); } set { MyValue = value; } }
Because the infinite loop would eventually cause a StackOverflowException to be thrown.
Because without a variable you'd end up with an endless recursion, causing a stack overflow :-)
public int MyValue
{
get { return MyValue; }
set { MyValue = value; }
}
Thus you need a backing field. The reason to keep the backing field private is to hide the implementation details. If it were public it wouldn't make any sense to declare a property to access it.
Why can't I just skip the private variable and do this...
public int MyValue { get { return MyValue; } set { MyValue = value; } }
Because return MyValue would recursively call the get accessor of the MyValue property, resulting in infinite recursion, and eventually a StackOverflowException (and similarly, MyValue = value would do the same with the set accessor)
The getter and setters are there with a backing property in case you want to do some kind of validation. If not then use auto properties, before auto properties were implemented this question came up and that's why they were implemented.
As said earlier this would cause a stack overflow, the reason for that is that when you type MyValue = value you will be calling the set again in a infinit loop until the program runs out of stack space, and the same happens for the get.
public int MyValue { get { return MyValue; } set { MyValue = value; } }
In additional to Ians response, they allow you to initialze the property to a default value of your choosing, rather than null:
private string _myString = string.Empty;
public string MyString
{
get{ return _myString;}
set{ _myString = value;}
}
will return string.Empty rather than null if the setter has never been called.