I am using DevExpress XAF Framework.
I have a Class with a lot of Persistent Alias Attributes that does some math on the properties. Here is an example of my code:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
}
I have tried setting the Property to = 1
return DebtEquity = 1;
But all this does is reset the property to 1 on saving.
I have tried setting the Default Value in SQL Server for each property to 1. But this does not work either.
Basically, I have a Detailview that has a bunch of calculations on it. And when I want to create a NEW Detail View, I get a DivideByZeroException because of course a NEW Detail View/Object is not going to have any values. Any ideas how I can get around this?
If you can get the value of EquityTotal then you can check it for zero first, otherwise you can catch the exception.
Example with check value first:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
if (EquityTotal == 0) return 0; // return 0 or whatever number you want when EquityTotal is equal to zero
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
}
Example with catch exception:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
try
{
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
catch (DivideByZeroException)
{
return 0; // return 0 or whatever number you want when EquityTotal is equal to zero
}
}
}
As an alternative using pure criteria language syntax, you can use:
[PersistentAlias("Iif(EquityTotal > 0,ShortTermDebt+LongTermDebt/EquityTotal, 0)")]
public decimal DebtEquity
{
get => Convert.ToDecimal(EvaluateAlias(nameof(DebtEquity)))
}
Related
I am trying to write this Program that gives the user the checkBox and then the user chooses One or Two and the Program will return the answer accordingly. but the program is not accepting the && Operator. if the user checks two boxes the program is only returning the result of the first checkBox not the second. it is not even adding.
This is the Code:
private double Oillube()
{
//checking if the Oil is checked
if (oilChbox.Checked)
{
return OIL_CHANGE;
}
//checking if the lube is checked
if (lubeChbox.Checked)
{
return LUBE_JOB;
}
//if they are both checked
if(lubeChbox.Checked && oilChbox.Checked)
{
//Creating Variables sum to hold the value of the two
double sum;
sum = OIL_CHANGE + LUBE_JOB;
//returning sum
return sum;
}
else
{
//just returning to get ride off the red line under the Method
return 0;
}
}
Since the AND condition is more restrictive than the others, you should check it first. Like this:
private double Oillube()
{
//if they are both checked
if(lubeChbox.Checked && oilChbox.Checked)
{
//Creating Variables sum to hold the value of the two
double sum;
sum = OIL_CHANGE + LUBE_JOB;
//returning sum
return sum;
}
//checking if the Oil is checked
if (oilChbox.Checked)
{
return OIL_CHANGE;
}
//checking if the lube is checked
if (lubeChbox.Checked)
{
return LUBE_JOB;
}
//just returning to get ride off the red line under the Method
return 0;
}
The lubeChbox.Checked && oilChbox.Checked condition needs to go first, as it is the more specific of the two.
The way you have it now if either lubeChbox.Checked is true, or oilChbox.Checked is true it will return before reaching the lubeChbox.Checked && oilChbox.Checked condition, meaning there is no situation in which it could ever reach the condition unless both were false.
This is why it is typically a bad idea for people to use return in this manner unless they fully understand the flow of the code they want to achieve.
Here's the corrected code:
private double Oillube()
{
//if they are both checked
if(lubeChbox.Checked && oilChbox.Checked)
{
//Creating Variables sum to hold the value of the two
double sum;
sum = OIL_CHANGE + LUBE_JOB;
//returning sum
return sum;
}
//checking if the Oil is checked
if (oilChbox.Checked)
{
return OIL_CHANGE;
}
//checking if the lube is checked
if (lubeChbox.Checked)
{
return LUBE_JOB;
}
//just returning to get ride off the red line under the Method
return 0;
}
Alternatively you can use tertiary operators for this situation like so:
private double Oillube()
{
return (lubeChbox.Checked ? LUBE_JOB : 0) + (oilChbox.Checked ? OIL_CHANGE : 0);
}
A tertiary operator works the same as an if statement only they work inline.
So this:
(lubeChbox.Checked ? LUBE_JOB : 0)
is equivalent to this pseudo-code:
if(lubeChbox.Checked) { LUBE_JOB } else { 0 }
Dotnetfiddle example
It's because if the first checkbox is checked, then first if statement is true, so you are returning value, thus ending the method.
You should replace your if statements, last one should become first, as it is most restrictive.
I sort a List with my own IComparer and this works just fine when running the application (XNA game) for more than an hour. But then, suddenly, I sometimes get the following error when invoking the sort-method with my custom Comparer:
An unhandled exception of type 'System.ArgumentException' occured in mscorlib.dll
Additional Information: ArgumentException
This is the line where the exception is thrown:
List<Continent> markets = new List<Continent>();
// filling the markets list ...
markets.Sort(new MarketCostCoverComparer(this));
and this is my class implementing IComparer interface:
class MarketCostCoverComparer : IComparer<Continent> {
private Player player;
public MarketCostCoverComparer(Player player) {
this.player=player;
}
public int Compare(Continent c1, Continent c2) {
if(player.GetCostCovering(c1)<player.GetCostCovering(c2)) {
return +1;
} else if(player.GetCostCovering(c1)==player.GetCostCovering(c2)) {
return 0;
} else {
return -1;
}
}
}
Here some methods that are linked to the comparer...:
public float GetCostCovering(Continent continent) {
// cover<1 => bad | cover>1 => good
if(GetOilfieldTheoreticOutput(continent.Type, true)<continent.Economy.CurrentDemand) {
return ((float)((GetOilfieldTheoreticOutput(continent.Type, true)*continent.Economy.CurrentPrice)))/(float)GetOilfieldCosts(continent.Type, true);
} else {
return ((float)((continent.Economy.CurrentDemand*continent.Economy.CurrentPrice)))/(float)GetOilfieldCosts(continent.Type, true);
}
}
public int GetOilfieldTheoreticOutput(ContinentType continent, bool drilled) {
int total = 0;
foreach(Oilfield oilfield in worldmap.Continents[(int)continent].Oilfields) {
if(oilfield.Owner==this && oilfield.Drilled==drilled) {
total+=oilfield.TheoreticOutput;
}
}
return total;
}
public int GetOilfieldCosts(ContinentType continent, bool drilled) {
int total = 0;
foreach(Oilfield oilfield in worldmap.Continents[(int)continent].Oilfields) {
if(oilfield.Owner==this && oilfield.Drilled==drilled) {
total+=oilfield.Costs;
}
}
return total;
}
Here the screenshot of the exception:
Here a closer look of the Locals/Stack-Trace (this is an old screenshot, but I will try to reproduce this exception within the next hours, so that I can expand the trace):
The problem is your implementation of your IComparer. It can return inconsistent results, so the sort function will throw an exception.
Maybe have a look at this and this question for more information.
Question:
Are the properties continent.Economy.CurrentDemand and continent.Economy.CurrentPrice free of side effects?
Remarks:
Your IComparer should be able to handle null. From the docs:
Comparing null with any type is allowed and does not generate an
exception when using IComparable. When sorting, null is considered to
be less than any other object.
Maybe it is an floating point issue, but that's just a wild guess. So maybe you should use decimal instead of float.
This is an other answer I got from Steve (from the XNA forums):
Apparently this can occur when you don't return 0 for both objects being the same. Is there any chance that GetCostCovering(c1) may not equal GetCostCovering(c2) at any point when they both reference the same object?
For safety sake, try putting if (c1 == c2) return 0; at the start of the Compare method and see how that works out.
Many thanks Steve!
If I remember correctly, IComparer.Compare should return less than zero if first argument is less than second argument. You seem to do the opposite in your implementation, which would explain the exception. I can't explain though why it is working for a long time before this failure...
I'm not quite sure how to ask my question in C# terms, so please bear with the long-winded explanation.
I'm writing a stock trading algorithm. When the algo starts, it checks to see what kind of instrument it is applied to (in this case, either stock or futures), and then depending on the instrument, assigns a value to "double x".
If its a future instrument, then the assignment is a simple, flat value (in this case, "double x = 5;). However, if its a stock, I'd like "x" to be assigned to a value from another object - lets call the object "Algo2" and the value "y". So, in my script the assignment is as follows: "double x = Algo2.y" (note: that's the convention in the editor I'm using). This block of code is run only once when the algorithm begins.
What I'm trying to achieve here is to tell my algorithm to get the latest value of "Algo2.y" whenever "x" is used in a formula such as "EntryValue = Price + x". However, whats happening is that "x" is permanently assigned the value of "Algo2.y" at the start of the program, and since that block is never run again, remains that constant value throughout.
Can anyone help with the syntax so that instead of assigning a value to "x", it simply points to get the latest value of "Algo2.y" whevever it's called?
Thanks!
Make 'x' a property, so that it fetches the value each time you ask for x.
class StockInstrument
{
public double Value //x isn't a good name, I'll use "Value"
{
get
{
if(...) return 5.0;
else return Algo2.y;
}
}
}
Write a function for it:
double getAlgo2YValue()
{
return Algo2.y; // or Algo2.getY(), another function if you can't access it
}
In your main algorithm, now call:
x = getAlgo2YValue();
To update X.
I would use a method to return your latest value
public double GetXValue()
{
if (AlgoType == Algos.Futures)
{
return 5.0;
}
else if (AlgoType == Algos.Stock)
{
return Algo2.y;
}
//else
throw new Exception("unknown algo type");
}
This is quite hard coded, but it could be cleaned up using delegates and encapsulation of the algorithms, but at a low level - this is the idea. Also, some people prefer to use properties for this - Just don't use properties when the get has modifying affects
public double X
{
get
{
if (AlgoType == Algos.Futures)
{
return 5.0;
}
else if (AlgoType == Algos.Stock)
{
return Algo2.y;
}
//else
throw new Exception("unknown algo type");
}
}
May use something like:
double X {
get {
if(isStock())
return Algo2.y;
else
return 5;
}
}
Func<int> getX;
if(isFuture)
getX = () => 5;
else
getX = () => Algo.y;
// using getX() will always return the current value of Algo.y,
// in case it's a stock.
int xval = getX();
Give Algo2 a reference to Algo so that no 'double X' copy is needed. Algo can then dereference the actual value in Algo2 at any time, (thread-safety an issue?).
Value data types, such as int are always going to be copied by value, not as a reference. However, what you can do is architect your solution a little differently, and then it will provide the right value. For example:
public class ValueContainer
{
protected Algo2 _reference = null;
protected double _staticValue = 0;
public double CurrentValue
{
get
{
if(_reference == null)
return _staticValue;
return _reference.y;
}
}
public ValueContainer(Algo2 reference)
{
_reference = reference;
}
public ValueContainer(double value)
{
_staticValue = value;
}
}
Then, you replace your x with the ValueContainer instance wherever needed and use the CurrentValue property to get the value. You create each version with a different constructor then:
ValueContainer container = null;
if(stock)
container = new ValueContainer(5);
else
container = new ValueContainer(Algo2);
What you need is a property wrapper for x to control the value that's returned, based on the instrument type. Here's an example, which will require some significant adaptation for your app.
public class Instrument
{
// an example enum holding types
public InstrumentType Type {get; set;}
// x is not a great name, but following your question's convention...
public double X
{
get
{
if(type == InstrumentType.Stock)
return Algo2.y();
// note that I changed this to be a method rather than a property
// Algo2.y() should be static so it can be called without an instance
else if(type == InstrumentType.Future)
return 5.0;
else
// return some default value here
}
}
}
I am trying to create a Collection with properties and their respective accessors.
Here is my code:
class SongCollection : List<Song>
{
private string playedCount;
private int totalLength;
public string PlayedCount
{
get
{
foreach (Song s in this)
{
if (s.TimesPlayed > 0)
{
return s.ToString();
}
}
}
}
public int TotalLength
{
get
{
foreach (Song s in this)
{
int total = 0;
total += s.LengthInSeconds;
}
return total;
}
}
}
I'm receiving the error at the "get" point. It tells me that not all code paths return a value... What exactly does this mean, and what am I missing?
Firstly, the reason you're getting that message is that if this is empty, then the code within the foreach block (which is where the required return statement is) would never be executed.
However, your TotalLength() function would always return the length of the first Song, as you're declaring your variable, setting its value, then returning it within the foreach block. Instead, you'd need to do something like this:
int totalLength = 0;
foreach(Song s in this)
{
total += s.LengthInSeconds;
}
return totalLength;
Your PlayedCount function suffers from similar issues (if the collection is empty or contains no elements whose TimesPlayed property is greater than 0, then there would be no way for it to return a value), so judging by your comment you could write it this way:
public int PlayedCount()
{
int total = 0;
foreach(Song s in this)
{
if (s.TimesPlayed > 0)
{
total++;
}
}
return total;
}
It means just as it says, not all code paths return a value.
In this case, if your list is empty, then it cannot call return. In a foreach, there must be at least one item for the code to execute. Now, maybe you know that the list will always contain a value, but the compiler can't know that
What would your method return if this did not evaluate?
if (s.TimesPlayed > 0)
{
return s.ToString();
}
try using an else to return an empty string or something
The fact that 'this' could have no songs- in that case the loops will not execute at all and there is no implicit return value in C#.
Furthermore, your getters don't really make sense unless you only ever had one song in the collection. You need something more like this:
public int TotalLength()
{
get
{
int total = 0;
foreach (Song s in this)
{
total += s.LengthInSeconds;
}
return total;
}
}
Finally, without knowing how you keep track of TimesPlayed for each individual song, I wouldn't know how to implement that getter, but I am sure you can figure it out with this much.
the following is my property where if we enter 45 then it appends 45.00 but then again it results in 45 because the value is converted from string. So what is the easiest way i can achieve this goal. Where if they enter 45 then it would result 45.00 in the value field;
public decimal Length
{
get { if (this is Detail)
return ((this as Detail).Length.ToString() == string.Empty)
? 0 : (this as Detail).Length; else return 0; }
set
{
if (this is Detail)
{
string val = string.Empty;
if (!value.ToString().Contains("."))
{
val = string.Format("{0}{1}", value.ToString(), ".00");
value =Math.Round(Convert.ToDecimal(val), 2);
}
else
value = Math.Round(value, 2);
(this as Detail).Length = (value.ToString().Trim() ==
string.Empty) ? 0 : value;
}
}
}
val = string.Format("{0:0.00}", value);
This has nothing to do with the property setter. You need to specify the string format in your GUI to round the numbers.
Also if (this is PersonalDetail) is a massive design flaw. Override the Length property in the PersonalDetail class instead. (not sure what the intent is with this property)
The problem is that 45m and 45.00m are the same thing, and since this is a decimal, it will always display "45" instead of "45.00" unless you use a string formatter every time you try to output it.
You could always make another property that does output what you want, such as:
public decimal Length { get; set; }
public string FormattedLength
{
get
{
return String.Format("{0:0.00}", this.Length);
}
}
On a side note I don't like this, but I believe it gets you more or less what you are looking for.