Track two types of values within one variable
-
I'm still new, so I don't know if this is the best way to do what I am needing, and would like some feedback/advice. I have a class that contains a double value. This double could represent a dollar value or it could represent a percentage value. Only one or the other, it will never have both. At runtime, I will need to be able to tell what type of value this is. Here is what I came up with, which appears to work, but if there is a better way, I would prefer that.
public class Rate
{
public double Value; // Holds either the dollar or percentage value
}
public class RateDollar : Rate {}
public class RatePercentage : Rate {}public class TransactionLine
{
// There's more stuff here, but it's not relevant to show
public Rate Amount;
}// Set the rate amount to be a dollar
myTransactionLine.Amount = new RateDollar();// I can check the type if needed
if(myTransactionLine.Amount.GetType() == typeof(RateDollar)) // We have a dollar value
if(myTransactionLine.Amount.GetType() == typeof(RatePercent)) // We have a percentage valueFor some reason, this seems like it is a clunky workaround. It also seems like it's possible for someone to create the value that is neither a RateDollar or RatePercent, and just as a plain Rate. Is there some way to prevent this, or is there a better way to accomplish what I am trying to do?
Lots of the responses here seem to be WAY over thinking things. 3 classes to hold a double value? Really? It doesn't seem like there is going to be any code in any of those 3 classes, so it should just be a single class with an enum indicating what it is. You aren't going to get around type checking all over the place. If you give us more info on what you are actually doing with the rates, we could provide more help. If its just for formatting, well, you would still have a single class and just override the ToString() that switches on the enum and formats with a % or $. And actually, the $ version should use the system formatter which formats currency according to the local settings.
-
Lots of the responses here seem to be WAY over thinking things. 3 classes to hold a double value? Really? It doesn't seem like there is going to be any code in any of those 3 classes, so it should just be a single class with an enum indicating what it is. You aren't going to get around type checking all over the place. If you give us more info on what you are actually doing with the rates, we could provide more help. If its just for formatting, well, you would still have a single class and just override the ToString() that switches on the enum and formats with a % or $. And actually, the $ version should use the system formatter which formats currency according to the local settings.
-
SledgeHammer01 wrote:
so it should just be a single class with an enum
A boolean would be sufficient.
jschell wrote:
A boolean would be sufficient.
Sure, if you know that you'll never add a 3rd type.
-
Definitely would not use an interface here. Whats the point? Not everything needs to be an interface. Having 3 classes (or interfaces or whatever) just to hold a double is over engineering at its finest :).
SledgeHammer01 wrote:
Definitely would not use an interface here. Whats the point?
Because he has not stated his reason for layers but is trying to use it. That is the point.
SledgeHammer01 wrote:
Having 3 classes (or interfaces or whatever) just to hold a double is over engineering at its finest
I have seen cases where an empty interface is even used. It is not over engineering. It is creating a base API. By what the OP was an interface is exactly what should be used.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
Lots of the responses here seem to be WAY over thinking things. 3 classes to hold a double value? Really? It doesn't seem like there is going to be any code in any of those 3 classes, so it should just be a single class with an enum indicating what it is. You aren't going to get around type checking all over the place. If you give us more info on what you are actually doing with the rates, we could provide more help. If its just for formatting, well, you would still have a single class and just override the ToString() that switches on the enum and formats with a % or $. And actually, the $ version should use the system formatter which formats currency according to the local settings.
Disappointing response. The responses are not over thinking. They are using what the OP posted and trying to provide an answer.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
SledgeHammer01 wrote:
Definitely would not use an interface here. Whats the point?
Because he has not stated his reason for layers but is trying to use it. That is the point.
SledgeHammer01 wrote:
Having 3 classes (or interfaces or whatever) just to hold a double is over engineering at its finest
I have seen cases where an empty interface is even used. It is not over engineering. It is creating a base API. By what the OP was an interface is exactly what should be used.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
Collin Jasnoch wrote:
Because he has not stated his reason for layers but is trying to use it. That is the point.
He did. He wanted to be able to tell the difference between a % and a $ amount. In which case an enum (or even a bool would suffice).
Collin Jasnoch wrote:
I have seen cases where an empty interface is even used. It is not over engineering. It is creating a base API.
By what the OP was an interface is exactly what should be used.
OP wanted to have a single double that held 2 different types of values and wanted to know a way to tell the difference between them. Using his GetType() solution required having 3 classes. The enum solution requires an enum & a single class. I'm not against interfaces, I use them all the time. I don't do stuff just cuz I can, I do stuff when its appropriate. I could also wear a tuxedo to go to Burger King, but I don't cuz that's slightly overkill :).
-
Disappointing response. The responses are not over thinking. They are using what the OP posted and trying to provide an answer.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
OP already explained what he wanted:
Quote:
I have a class that contains a double value. This double could represent a dollar value or it could represent a percentage value. Only one or the other, it will never have both. At runtime, I will need to be able to tell what type of value this is. Here is what I came up with, which appears to work, but if there is a better way, I would prefer that.
He wanted a class that holds a double value and a way to determine the type of data. He thought the GetType() solution was clunky.
-
Collin Jasnoch wrote:
Because he has not stated his reason for layers but is trying to use it. That is the point.
He did. He wanted to be able to tell the difference between a % and a $ amount. In which case an enum (or even a bool would suffice).
Collin Jasnoch wrote:
I have seen cases where an empty interface is even used. It is not over engineering. It is creating a base API.
By what the OP was an interface is exactly what should be used.
OP wanted to have a single double that held 2 different types of values and wanted to know a way to tell the difference between them. Using his GetType() solution required having 3 classes. The enum solution requires an enum & a single class. I'm not against interfaces, I use them all the time. I don't do stuff just cuz I can, I do stuff when its appropriate. I could also wear a tuxedo to go to Burger King, but I don't cuz that's slightly overkill :).
I worked from what he had. He "HAD" the layer set up. If you re-read what I post you "SHOULD" notice I question his usage of layers. He did respond and now you have the leisure to provide condescending remarks with 20/20. Good for you.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
OP already explained what he wanted:
Quote:
I have a class that contains a double value. This double could represent a dollar value or it could represent a percentage value. Only one or the other, it will never have both. At runtime, I will need to be able to tell what type of value this is. Here is what I came up with, which appears to work, but if there is a better way, I would prefer that.
He wanted a class that holds a double value and a way to determine the type of data. He thought the GetType() solution was clunky.
That is not exactly what his post states. Reading his other posts one can elude that.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
I'm still new, so I don't know if this is the best way to do what I am needing, and would like some feedback/advice. I have a class that contains a double value. This double could represent a dollar value or it could represent a percentage value. Only one or the other, it will never have both. At runtime, I will need to be able to tell what type of value this is. Here is what I came up with, which appears to work, but if there is a better way, I would prefer that.
public class Rate
{
public double Value; // Holds either the dollar or percentage value
}
public class RateDollar : Rate {}
public class RatePercentage : Rate {}public class TransactionLine
{
// There's more stuff here, but it's not relevant to show
public Rate Amount;
}// Set the rate amount to be a dollar
myTransactionLine.Amount = new RateDollar();// I can check the type if needed
if(myTransactionLine.Amount.GetType() == typeof(RateDollar)) // We have a dollar value
if(myTransactionLine.Amount.GetType() == typeof(RatePercent)) // We have a percentage valueFor some reason, this seems like it is a clunky workaround. It also seems like it's possible for someone to create the value that is neither a RateDollar or RatePercent, and just as a plain Rate. Is there some way to prevent this, or is there a better way to accomplish what I am trying to do?
I would be more inclined to use the enum over abstract classes and interface for something like this. Unless there is a deeper level of programming that isn't being shown I would stick with simplicity. This would be my interpetation of the object you are wanting also with a nice ToRateString() method so you can use the rate object to easily display your value in preformatted string.
Rate r = new Rate(ENRateType.Dollar, 5.58d);
//r.ToRateString() would display $5.58public enum ENRateType { Dollar, Percent } public class Rate { public Rate() { RateType = ENRateType.Dollar; Value = 0d; } public Rate(ENRateType rateType, double value) : this() { RateType = rateType; Value = value; } public ENRateType RateType {get; internal set;} public double Value { get; internal set; } public string ToRateString() { if (RateType == ENRateType.Dollar) return "$" + Value.ToString("0.00"); return Value.ToString("0.000") + "%"; } }
-
That is not exactly what his post states. Reading his other posts one can elude that.
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
SledgeHammer01 wrote:
so it should just be a single class with an enum
A boolean would be sufficient.
I agree that a boolean would work fine, but an enumeration would be a lot easier to read. What if by some chance he has his requirements change and needs to keep track of more than two types for the value? This whole thing could go to hell really quick then. Seems like a lot of over engineering going on here :)
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
-
I would be more inclined to use the enum over abstract classes and interface for something like this. Unless there is a deeper level of programming that isn't being shown I would stick with simplicity. This would be my interpetation of the object you are wanting also with a nice ToRateString() method so you can use the rate object to easily display your value in preformatted string.
Rate r = new Rate(ENRateType.Dollar, 5.58d);
//r.ToRateString() would display $5.58public enum ENRateType { Dollar, Percent } public class Rate { public Rate() { RateType = ENRateType.Dollar; Value = 0d; } public Rate(ENRateType rateType, double value) : this() { RateType = rateType; Value = value; } public ENRateType RateType {get; internal set;} public double Value { get; internal set; } public string ToRateString() { if (RateType == ENRateType.Dollar) return "$" + Value.ToString("0.00"); return Value.ToString("0.000") + "%"; } }
Trak4Net wrote:
stick with simplicity
Same here. At least try to keep things as simple as possible.
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
-
I'm still new, so I don't know if this is the best way to do what I am needing, and would like some feedback/advice. I have a class that contains a double value. This double could represent a dollar value or it could represent a percentage value. Only one or the other, it will never have both. At runtime, I will need to be able to tell what type of value this is. Here is what I came up with, which appears to work, but if there is a better way, I would prefer that.
public class Rate
{
public double Value; // Holds either the dollar or percentage value
}
public class RateDollar : Rate {}
public class RatePercentage : Rate {}public class TransactionLine
{
// There's more stuff here, but it's not relevant to show
public Rate Amount;
}// Set the rate amount to be a dollar
myTransactionLine.Amount = new RateDollar();// I can check the type if needed
if(myTransactionLine.Amount.GetType() == typeof(RateDollar)) // We have a dollar value
if(myTransactionLine.Amount.GetType() == typeof(RatePercent)) // We have a percentage valueFor some reason, this seems like it is a clunky workaround. It also seems like it's possible for someone to create the value that is neither a RateDollar or RatePercent, and just as a plain Rate. Is there some way to prevent this, or is there a better way to accomplish what I am trying to do?
From what I see there are several ways to do this: 1. Use class/interface inheritance 2. Use an enum 3. Use a boolean It all depends on what you want, If you want good control over the different types of rates you should use class/interface inheritance, if the dollar rate should have different functionality than say a euro rate (convert between rates etc...) Example:
interface Rate
{
double getValue();
}class DollarRate : Rate
{
double rawval; //the actual valueinternal double getValue() { return rawval \* 6; //format in the way you want }
}
class PercetageRate : Rate
{
double rawval; //again, the valueinternal double getValue() { return rawval; //I just use the raw value for percentage }
}
class EuroRate : Rate
{
double rawval;internal double getValue() { return rawval \* 9; //some other rate }
}
void Main()
{
if(myTransactionLine.Amount is DollarRate)
{
//do dollar
}
else if(myTransactionLine.Amount is PercetageRate)
{
//do percentage
}
//continue...
}If you don't need this then just use the enum approach to save time and space. I also came up with my own approach, I think it's the fastest one that allows for more than 2 rates (IE the bool method) It works like the enum approach but instead of enums you use constants. (It's faster because constants are converted to a raw value at compile time) Example:
static class Rates
{
//you can use whatever datatype you want, I choose byte since its 4 times smaller than int and can hold 256 cominations (including 0). You could also use chars: DOLLAR = '$', PERCENTAGE = '%', EURO = '€' etc...
public const byte DOLLAR = 0;
public const byte PERCENTAGE = 1;
public const byte EURO = 2;
//add more constants for more rates
}class Rate
{
double value;
byte type; //the type of the rateinternal double Value { get { return value; } } internal byte Type { get { return type; } }
}
void Main()
{
if(myTransactionLine.Amount.Type == Rates.DOLLAR)
{
//do dollar
}
else if(myTransactionLine.Amount is Rates.PERCENTAGE)
{
//do percentage
}
//continue...
}Hope this helps! Sorry for long post...
-
Thanks for responding! I haven't really gotten to learning a lot about interfaces (or abstract classes), but I am thinking that will be the next topic I tackle. The reason for this setup is because I am interacting with another software, and that software has one value that represents either a dollar value or a percentage. For example, this is how it would show a transaction:
Widget $12.00
Shipping $3.95
Subtotal $15.95
Tax 8.875%
Total $30.11When I get this information from the program, they have a rate class that contains three members, an enum for the price type (dollar or percent), a double for the Dollar value, and a double for the Percent value. Because the line can only be a dollar or value and not both, one of the doubles will always be null. I get the feeling (but I may be wrong) that they way they did their setup isn't the best. I will probably implement a Rate class that contains an enum and a double, which should work, but if there is a 'better' way to do this, I would prefer to learn about that type of implementation.
To me this information indicates you are "free" to change the Rate class in the program you get the information from: is that correct ? The use of the phrases "They have," and "they did," and, "I am interacting with another software," is what gives me the idea you may not have freedom to change the Rate class. thanks, Bill
"Everything we call real is made of things that cannot be regarded as real." Niels Bohr
-
I'm still new, so I don't know if this is the best way to do what I am needing, and would like some feedback/advice. I have a class that contains a double value. This double could represent a dollar value or it could represent a percentage value. Only one or the other, it will never have both. At runtime, I will need to be able to tell what type of value this is. Here is what I came up with, which appears to work, but if there is a better way, I would prefer that.
public class Rate
{
public double Value; // Holds either the dollar or percentage value
}
public class RateDollar : Rate {}
public class RatePercentage : Rate {}public class TransactionLine
{
// There's more stuff here, but it's not relevant to show
public Rate Amount;
}// Set the rate amount to be a dollar
myTransactionLine.Amount = new RateDollar();// I can check the type if needed
if(myTransactionLine.Amount.GetType() == typeof(RateDollar)) // We have a dollar value
if(myTransactionLine.Amount.GetType() == typeof(RatePercent)) // We have a percentage valueFor some reason, this seems like it is a clunky workaround. It also seems like it's possible for someone to create the value that is neither a RateDollar or RatePercent, and just as a plain Rate. Is there some way to prevent this, or is there a better way to accomplish what I am trying to do?
As is often the case with newish people, I don't think you've actually asked the right question. What's your real requirement here? From reading the thread, it appears to be that you want a surcharge, either a percentage or a fixed amount, to be applied to a bill. What's the interface to that?
interface ISurcharge {
double GetAmount(Order order);
string Name { get; }
}... or, if it's just on the amount, you can pass a number instead of an order. My guess, though, is different tax rates may apply to different items so you will eventually need to pass the order. Note the important thing here: the value of the surcharge depends (in general) on the existing order so it needs to be part of the interface. The Name property is for what gets displayed on the bill; you may want a few other little things like that, but this is the core functionality. Now you can create trivial implementation classes to solve the problem!
class FixedSurcharge : ISurcharge {
private double amount;
public string Name { get; private set; }
public FixedSurcharge(string name, double amount) { Name = name; this.amount = amount; }
public double GetAmount(Order order) { return amount; }
}class PercentageSurcharge : ISurcharge {
private double percentage;
public string Name { get; private set; }
public PercentageSurcharge (string name, double percentage) { Name = name; this.percentage = percentage; }
public double GetAmount(Order order) { return percentage * 0.01 * order.TotalValue; }
}... called like:
void placeOrder(Order order){
foreach(OrderItem item in order.Items) { addBillItem(item.Name, item.Value); }
addSurcharge(new PercentageSurcharge("VAT", 20), order);
addSurcharge(new FixedSurcharge("Shipping", 2.50), order);
}void addSurcharge(ISurcharge surcharge, Order order){
addBillItem(surcharge.Name, surcharge.GetAmount(order));
}(Actually, on reflection it may be cleaner to make fake order items, with a Value property, by passing the existing Order to a constructor and stashing it in the Surcharge instance. That's a matter of style, I think.)