I have many classes with int, decimal variables in my C# application.
Consider the following example.
public class Employee
{
decimal TotalSalary;
public decimal Salary
{
get
{
return TotalSalary;
}
set
{
TotalSalary = value;
}
}
public string GetSalary()
{
return TotalSalary.ToString();
}
}
public class Contract
{
Employee emp1 = new Employee();
public void ProcessSalary()
{
emp1.Salary = 100000;
SendToLabel(emp1.GetSalary());
}
}
In the above example whenever I use "ToString" of any decimal/int variable in my application, it should give me the number in Indian numbering format like below.
100000 should render as 1,00,000
10000 should render as 10,000
This should happen globally in my C# .NET application.
Can I do this using CultureInfo in global.asax page.
Right now for formatting date i am using the following code.
CultureInfo newCulture = (CultureInfo) System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "dd-MMM-yyyy";
newCulture.DateTimeFormat.DateSeparator = "-";
Thread.CurrentThread.CurrentCulture = newCulture;
Following code will be useful to you,
public string GetSalary()
{
CultureInfo inr = new CultureInfo("hi-IN");
return string.Format(inr, "{0:#,#}", TotalSalary);
}
whenever I use "ToString" of any decimal/int variable in my application, it should give me the number in Indian numbering format
You could also make a new method as extension for the types decimal and int:
public static class MyExtensions
{
public static string MyOutput(this decimal number)
{
return number.ToString("#,#.##", new CultureInfo(0x0439));
}
public static string MyOutput(this int number)
{
return number.ToString("#,#", new CultureInfo(0x0439));
}
}
All culture codes for further reference.
Then you can use it throughout your programm for variables of the decimal/int types:
public string GetSalary()
{
return TotalSalary.MyOutput();
}
Output: for decimal asd = 1000000.23m;
10,00,000.23
The signature of the GetSalary will be like this:
public string GetSalary()
{
return String.Format("{0:n}", TotalSalary);
}
Working Example
You can use "{0:n3}" if you want to round off decimals to 3 digits.
Related
I have 3 classes (1 absrtact(Services), and 2 derivatives). Plus, I have 2 different output formats (UA/EN). And I don't know how remake my code in order it follow a open closed principle. For example, if I want to add a German output format. I will need to edit each class.
using System;
using System.Globalization;
namespace naslidov
{
public abstract class Services
{
public string title;
public decimal price;
public Services(string title, decimal price)
{
this.title = title;
this.price = price;
}
public virtual string ToEnglish()
{
return $" ";
}
public virtual string ToUkraine()
{
return $"";
}
}
public class Food : Services
{
public DateTime expirationDate;
public Food(string title, decimal price, DateTime expirationDate)
: base(title, price)
{
this.title = title;
this.price = price;
this.expirationDate = expirationDate;
}
public override string ToEnglish()
{
return $"{base.title} |{price.ToString("N", CultureInfo.InvariantCulture)} uan | {expirationDate.ToString("d", CultureInfo.CreateSpecificCulture("ja-JP"))} |------ ";
}
public override string ToUkraine()
{
return $"{base.title} |{price.ToString("F", CultureInfo.InvariantCulture).Replace(".", ",")} uan | {expirationDate.ToString("dd.MM.yyyy")}| ------ ";
}
}
public class HouseholdAppliance : Services
{
public int warrantyPeriodInMonths;
public HouseholdAppliance(string title, decimal price, int warrantyPeriodInMonths)
: base(title, price)
{
this.title = title;
this.price = price;
this.warrantyPeriodInMonths = warrantyPeriodInMonths;
}
public override string ToEnglish()
{
return $"{base.title} |{price.ToString("N", CultureInfo.InvariantCulture)} uan | ------ |{warrantyPeriodInMonths} ";
}
public override string ToUkraine()
{
return $"{base.title} |{price.ToString("F", CultureInfo.InvariantCulture).Replace(".", ",")} uan | ------ |{warrantyPeriodInMonths} ";
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter region(UA/EN):");
string user_input = Console.ReadLine();
DateTime date1 = new DateTime(2002, 3, 25);
DateTime date2 = new DateTime(2022, 8, 17);
DateTime date3 = new DateTime(2005, 1, 10);
Services first = new Food("apple", 105324660120.58m, date1);
Services second = new Food("bananas", 3045.21m, date2);
Services third = new Food("nuts", 308540m, date3);
Services nofrst = new HouseholdAppliance("television", 25547.54m, 12);
Services noscd = new HouseholdAppliance("pilosos", 2756854m, 24);
Services nothir = new HouseholdAppliance("notebook", 32248, 36);
Services[] fullservices = new Services[] { first, second, third, nofrst, noscd, nothir };
Console.WriteLine("title | price | expirationDate | warrantyPeriodInMonths");
Console.WriteLine("-----------------------------------------------------------------------");
if (user_input == "EN")
{
foreach (Services fullservice in fullservices)
{
Console.WriteLine(fullservice.ToEnglish());
}
}
if (user_input == "UA")
{
foreach (Services fullservice in fullservices)
{
Console.WriteLine(fullservice.ToUkraine());
}
}
else if (user_input != "UA" && user_input != "EN")
{
Console.WriteLine(" Sorry, wrong input!");
}
}
}
}
First of all, I want to encourage to never refactor without a requirement or goal. If you are trying to refactor this code to make it extensible for something you don't know needs to be extended, you are not only likely to be wasting effort (YAGNI), but you may also end up with code that is harder to change in other ways you might need later.
Thus, for the purposes of this answer, I will assume that the requirement is to make this code extensible (open for extension). And that what you need to extend is the supported formats.
We will start by defining a new abstract class Formatter interface IFormat which will serve as extension point to add new format. Ideally, this IFormat should not depend on any specific (concrete, not abstract) Services, nor should Services know about any specific IFormat. That is, we want extending these to be as independent as possible.
Now, what do specific Services need to format? I can see in the code that you need to know the format for dates and prices. So let us give methods to format those to IFormat:
public interface IFormat
{
string FormatDate(DateTime date);
string FormatPrice(decimal price);
}
Add any other methods that make sense. I added the minimum for this case.
We can proceed to implement a formatter for English and one for Ukrane. Please excuse my naming convention.
public class FormatterEnglish : IFormat
{
public string FormatDate(DateTime date)
{
return date.ToString("d", CultureInfo.CreateSpecificCulture("ja-JP"));
}
public string FormatPrice(decimal price)
{
return price.ToString("N", CultureInfo.InvariantCulture);
}
}
public class FormatterUkrane : IFormat
{
public string FormatDate(DateTime date)
{
return date.ToString("dd.MM.yyyy");
}
public string FormatPrice(decimal price)
{
return price.ToString("F", CultureInfo.InvariantCulture).Replace(".", ",");
}
}
Now, let us rework Services to use it. It will no longer have one method per format, but one single method that takes a IFormat argument:
public abstract class Services
{
public decimal price;
public string title;
public Services(string title, decimal price)
{
this.title = title;
this.price = price;
}
public abstract string ToString(IFormat formatter);
}
And, of course, we need to implement it in HouseholdAppliance:
public override string ToString(IFormat formatter)
{
return $"{base.title} |{formatter.FormatPrice(price)} uan | ------ |{warrantyPeriodInMonths} ";
}
And Food:
public override string ToString(IFormat formatter)
{
return $"{base.title} |{formatter.FormatPrice(price)} uan | {formatter.FormatDate(expirationDate)} |------ ";
}
To choose our IFormat, I suggest a factory method. For example:
private static IFormat? CreateFormatter(string formatName)
{
if (formatName == "EN")
{
return new FormatterEnglish();
}
if (formatName == "UA")
{
return new FormatterUkrane();
}
return null;
}
You may also be interested in using type discovery, and specifying the format name in a custom attribute. That is beyond the scope of this answer.
Finally, you can use it like this:
var formatter = CreateFormatter(user_input);
if (formatter == null)
{
Console.WriteLine(" Sorry, wrong input!");
return;
}
foreach (Services fullservice in fullservices)
{
Console.WriteLine(fullservice.ToString(formatter));
}
Having a second look at the code, it is possible to extract the format template from the Services. The IFormat would need the template and the data. A solution like FormatWith would make that easier. Anyway, I believe this answer addresses the question as it is.
I'm trying to pass method values along between forms. As a result, I've made the methods whose data I want to pass along static. Since I'm using non-static text boxes to gather user input, I've also made public property methods to parse the input from the user, store its value in a public class-level static variable, and return the value to the static methods which call the variable.
public static int laborHours;
public int lHoursB
{
get
{
return laborHours;
}
set
{
laborHours = int.Parse(lHours.Text);
}
}
private static decimal laborMethod(decimal laborTotal)
{
const decimal laborCharge = 50M;
decimal labor = 0;
labor = laborCharge * laborHours;
return labor;
}
public static decimal amountCharged;
public decimal amount
{
get
{
return amountCharged;
}
set
{
amountCharged = int.Parse(amtBox.Text);
}
}
public static int numberOfParts;
public int partsNumber
{
get
{
return numberOfParts;
}
set
{
numberOfParts = int.Parse(partsBox.Text);
}
}
private static decimal subtotalMethod(decimal subTotal)
{
decimal subtotal = 0;
subtotal = amountCharged * numberOfParts;
return subtotal;
}
private static decimal subtotal2Method(decimal subtotalTwo)
{
decimal labor = 0;
decimal subtotal = 0;
labor = laborMethod(labor);
subtotal = subtotalMethod(subtotal);
subtotalTwo = subtotal + labor;
return subtotalTwo;
}
private static decimal taxMethod(decimal salesTax)
{
const decimal tax = .08M;
decimal sTax = 0;
decimal sub = 0;
sub = subtotalMethod(sub);
sTax = sub * tax;
return sTax;
}
The compiler checks everything out as a clean compile, but there's a logic error here I can't seem to find. When I run a simple test with the program, every text box returns a "0".
Help, please?
Your properties are back to front compared to the normal way they are written. I suggest you write them like this instead:
public int lHoursB
{
get
{
int result = 0;
int.TryParse(lHours.Text, out result);
return result;
}
set
{
lHours.Text = value.ToString();
}
}
Then you can do:
lHoursB = 10;
which will set the lHours textbox to "10". I have used TryParse and not Parse, as the latter will throw a FormatException if it cannot parse the string; you may prefer to have an exception, in which case use Parse. Also you should use Decimal.Parse/TryParse and not Int32.Parse for amount, which is a decimal and not an int. Finally, you can specify a culture in the int.ToString call, if you want to format the int for a specific culture (see Int32.ToString()).
I want to format the decimal places displayed and captured in a DataGridView, I have a minimum number of decimal places and a maximum number of decimal places.
For example:
If caught, "120.0" display "120.00"
If caught "120.01" display "120.01"
If caught "120,123" display "120,123"
If caught "120.1234" display "120.1234"
If caught "120.12348" display "120.1235" (round)
In the DataGridView column "txtcDecimal" has the property (from the designer)
txtcDecimal.DefaultCellStyle.Format = "N2";
txtcDecimal.DefaultCellStyle.Format = "0.00##"; // IS ANSWER. I do not work for an event that interfered
the mask "0.00##" work as "n2" only get 2 decimals
which does the correct rounding to two decimal places but just do not like what I need (as I show in the example)
How I can do it in a simple manner without consuming many resources?
Thanks harlam357 & Tom Garske
To format between 2 and 4 decimal places you can use a custom format string.
txtcDecimal.DefaultCellStyle.Format = "0.00##"
To go a bit further...
public partial class Form1
{
public Form1()
{
InitializeComponent();
var list = new List<Data>();
list.Add(new Data { Prop1 = 1, Prop2 = 1.2 });
list.Add(new Data { Prop1 = 2, Prop2 = 1.234567 });
dataGridView1.Columns.Add("Prop1", "Prop1");
dataGridView1.Columns["Prop1"].DataPropertyName = "Prop1";
dataGridView1.Columns.Add("Prop2", "Prop2");
dataGridView1.Columns["Prop2"].DataPropertyName = "Prop2";
dataGridView1.Columns["Prop2"].DefaultCellStyle.Format = "0.00##";
dataGridView1.DataSource = list;
}
class Data
{
public int Prop1 { get; set; }
public double Prop2 { get; set; }
}
}
To format between 2 and 4 decimal places you can use a custom format string. (As provided by Harlam357)
txtcDecimal.DefaultCellStyle.Format = "0.00##"
I verified it with the following simple console application:
double myDouble = 13.1;
double myDouble2 = 13.12345;
Console.WriteLine(myDouble.ToString("0.00##"));
Console.WriteLine(myDouble2.ToString("0.00##"));
Console.Read();
The output was:
13.10
13.1235
Harlam's answer is clearly correct....
UPDATE: This is how I implemented it in forms:
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("a");
dt.Rows.Add(123.4);
dt.Rows.Add(123.45);
dt.Rows.Add(123.456);
dt.Rows.Add(123.4567);
dt.Rows.Add(123.45678);
this.dataGridView1.DataSource = dt;
this.dataGridView1.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);
}
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex != this.dataGridView1.NewRowIndex)
{
double d = double.Parse(e.Value.ToString());
e.Value = d.ToString("0.00##");
}
}
SOURCE: http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/95e7e7ef-2e71-412f-abe5-ffbee2c12c18/
OUTPUT:
Create a custom formatter.
public class MyFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
// Check whether this is an appropriate callback
if (!this.Equals(formatProvider))
return null;
//if argument/ value is null we return empty string
if (arg == null)
return null;
string resultString = arg.ToString();
//transform resultString any way you want (could do operations based on given format parameter)
//return the resultant string
return resultString;
}
}
SOURCE: How to custom format data in datagridview during databinding
I have the following code in a Calculations.cs class:
public decimal decPaymentPlan(QuoteData quoteData)
{
if (quoteData.StepFilingInformation.PaymentPlanRadioButton
== StepFilingInformation.PaymentPlan.No)
return PriceQuote.priceNoPaymentPlan;
else
return PriceQuote.pricePaymentPlanChapter7; //may want to switch
//to Chapter13 value
}
public decimal CalculateChapter7(QuoteData quoteData)
{
decimal total = PriceQuote.priceChapter7;
total += this.decPaymentPlan(quoteData); //want to be able to tell
//which to use, 7 or 13
return total;
}
I am trying to see if I can avoid an extra decPaymentPlan where the final return is pricePaymentPlanChapter13. I thought there might be a way to switch it out.
Otherwise, I'd have to do the following:
public decimal decPaymentPlanChapter7(QuoteData quoteData)
{
...
else
return PriceQuote.pricePaymentPlanChapter7;
}
public decimal decPaymentPlanChapter13(QuoteData quoteData)
{
...
else
return PriceQuote.pricePaymentPlanChapter13;
}
...
//the following will appear anyway, but rather than just using
//one method call which switches the choice based on something
public decimal CalculateChpater7(QuoteData quoteData)
{
...
//instead of decPaymentPlan(quoteData) + something to switch
total+= this.decPaymentPlanChapter7(quoteData);
...
}
public decimal CalculateChpater13(QuoteData quoteData)
{
...
//instead of decPaymentPlan(quoteData) + something to switch
total+= this.decPaymentPlanChapter13(quoteData);
...
}
Is something like this doable (and how)? Thanks. Appreciate any code samples or guidance.
UPDATE:
This is my controller:
public ActionResult EMailQuote()
{
Calculations calc = new Calculations();
QuoteData quoteData = new QuoteData
{
StepFilingInformation = new Models.StepFilingInformation
{
//just moking user input here temporarily to test out the UI
PaymentPlanRadioButton = Models.StepFilingInformation.PaymentPlan.Yes,
}
};
var total = calc.CalculatePrice(quoteData);
ViewBag.CalculatePrice = total; // ADDED THIS LINE
return View(quoteData);
}
Also, I set a value in PriceQuote for Chapter7 and Chapter 13 (e.g., public static decimal priceChapter7 { get { return 799; } }
Hard to be sure of a suggestion without understanding more about what you are doing, but if the only difference between your methods are a set of values to use (one set for chapter7, the other for chapter13) it may make sense to take these values out of PriceQuote and create a base type to hold these values. Then your decPaymentPlan and other methods would only take an instance of that type. For example:
class Chapter // for lack of a better name
{
public decimal PaymentPlan { get; set; }
public decimal Price { get; set; }
....
}
Then, change your methods to take a Chapter parameter
public decimal decPaymentPlan(QuoteData quoteData, Chapter chapter)
{
if (quoteData.StepFilingInformation.PaymentPlanRadioButton
== StepFilingInformation.PaymentPlan.No)
return PriceQuote.priceNoPaymentPlan;
else
return chapter.PaymentPlan;
}
public decimal Calculate(QuoteData quoteData, Chapter chapter)
{
decimal total = chapter.Price;
total += this.decPaymentPlan(quoteData, chapter);
return total;
}
Now all you would need are two instances of Chapter, one for 7 and the other for 13, and call your calculate method accordingly.
UPDATE: To elaborate a bit on what I mean by 'call your calculate method accordingly', lets say for example you had two static variables (somewhere that makes sense in your application, perhaps in Calculations.cs)
static Chapter Chapter7 = new Chapter() { Price = 799.99, PaymentPlan = 555.55 };
static Chapter Chapter13 = ...
Then in your controller, you would be able to write
ViewBag.Chapter7Total = calc.CalculatePrice(quoteData, Chapter7);
ViewBag.Chapter13Total = calc.CalculatePrice(quoteData, Chapter13);
What's the difference between 7 and 13? I would just opt into doing:
if (quoteData.StepFilingInformation.PaymentPlanRadioButton ==
StepFilingInformation.PaymentPlan.No)
return PriceQuote.priceNoPaymentPlan;
else if (//whatever fulfills ch. 7)
return PriceQuote.pricePaymentPlanChapter7;
else //ch. 13
return PriceQuote.pricePaymentPlanChapter13;
It looks like you could create an Enumeration of the Chapters and pass that in as a second parameter to the decPaymentPlan method yes?
You are mixing your business logic with your visualization layer:
if (quoteData.StepFilingInformation.PaymentPlanRadioButton
== StepFilingInformation.PaymentPlan.No)
A better design would be to have a model on which changes are applied e.g. MVC, MVP, MVVM.
Example:
public class View
{
private Model _model = new Model();
public View()
{
}
public Controller Controller
{
get;
set;
}
private void OnButton1Click(object sender, EventArgs args)
{
_model.Option = Options.Option1;
}
private void OnSaveClick(object sender, EventArgs args)
{
if (Controller != null)
Controller.ApplyChanges(_model);
}
}
The controller can then apply business logic free of the view structure, so that you can change either of the two freely.
E.g.
public class Controller
{
Model Model
{
get;
set;
}
decimal CalculateSum()
{
return Model.Items.Aggregate((a, b) => a + b);
}
}
I want to do an application that pareses text. So far, I have a class called Result, that holds the value and type each part of an equation.
public enum ResultType
{
Int32,
Double,
Boolean,
Color,
DateTime,
String,
Undefined,
Void
}
public class Result
{
public object Value { get; set; }
public ResultType Type { get; set; }
}
Possible Result's could be:
5 : Int32
true : Boolean
DADACC : Color
"Hello World!" : String
10.0 : Double
13/11/1986 : DateTime
Now I want to sum/divide/pow/... two Results but I really don´t want to do all the work. In C#, you can mix them all together and get an answer.
var value = "Hello" + 2.0 + 4 + DateTime.Today; (value = "Hello2413/09/2011 12:00:00 a.m.")
Is there an easy way to handle this? Or do I have to figure out all combos by myself? I´m thinking about something like:
var Operator = "+"; // or "-","*","/","^","%"
var sum = DoTheCSharpOperation(Operator, ResultA.Value, ResultB.Value)
var sumResult = new Result(sum);
This sounds to me like a perfect application for the "dynamic" keyword:
using System;
using System.Diagnostics;
namespace ConsoleApplication33 {
public static class Program {
private static void Main() {
var result1=DoTheCSharpOperation(Operator.Plus, 1.2, 2.4);
var result2=DoTheCSharpOperation(Operator.Plus, "Hello", 2.4);
var result3=DoTheCSharpOperation(Operator.Minus, 5, 2);
Debug.WriteLine(result1); //a double with value 3.6
Debug.WriteLine(result2); //a string with value "Hello2.4"
Debug.WriteLine(result3); //an int with value 3
}
public enum Operator {
Plus,
Minus
}
public static object DoTheCSharpOperation(Operator op, dynamic a, dynamic b) {
switch(op) {
case Operator.Plus:
return a+b;
case Operator.Minus:
return a-b;
default:
throw new Exception("unknown operator "+op);
}
}
}
}