How to get rid of conversion overheads? - c#

Take this example:
customer.Salary = Convert.ToDecimal(string.Format("{0}! ", Console.ReadLine().ToString()));
(1) Why in C# we need to always put .ToString() to get it right?
(2) Convert.To... Doesn't it creates overheads unnecessarily?
Further in the below given code: It gives error: "Input string was not in a correct format", after accepting user input.
// Main begins program execution.
public static void Main()
{
Customer customer = new Customer();
// Write to console/get input
Console.Write("Enter customer's salary: ");
customer.Salary = Convert.ToDecimal(string.Format("{0}! ", Console.ReadLine().ToString()));
Console.WriteLine("Salary in class variable is: {0}", customer.Salary.ToString());
Console.Read();
}
class Customer
{
public Decimal Salary { get; set; }
}
Here again, either I must use:
string sal = Convert.ToDecimal(string.Format("{0}! ", Console.ReadLine().ToString()));
customer.Salary = Convert.ToDecimal(sal);
Or, I must change the data type itself in the Customer class.
Can this overhead be avoided with anything in Generics?

You do not need to call .ToString().
Yes, it does.
You're trying to write
customer.Salary = Decimal.Parse(Console.ReadLine());
Your current code does the following:
Console.ReadLine(): Reads a line from the console, returning a String object.
(...).ToString() Returns the same String object
string.Format("{0}! ", (...)): Returns a new String object containing the original string followed by !.
Convert.ToDecimal((...)): Tries to parse that into a Decimal value.
Since the string ends with !, it fails

I think you'll be happier if you use Decimal.Parse or Decimal.TryParse to do the conversions, rather than relying on Convert.ToDecimal. You can write:
Decimal tempSal;
string sal = Console.ReadLine();
if (Decimal.TryParse(sal, out tempSal))
{
customer.Salary = tempSal;
}
else
{
// user entered bad data
}

Related

Why Console.WriteLine outputs text without a format string and the type name when using a format string?

I using the codes below to print out the reverse name of a user input but I couldn't understand why the Console.WriteLine call prints out "Your reverse name is: System.Char[]"? If I just type Console.WriteLine(reverseName), it print out the reverse name correctly. What is different in this code? Couldn't understand why the usage a placeholder would give different output? Isn't it refer to the same information in reverseName?
static void Main(string[] args)
{
var name = "Alice";
char[] reverseName = new char[name.Length];
for (var i = name.Length - 1; i > -1; i--)
{
reverseName[i] = name[name.Length - 1 - i];
}
Console.WriteLine(reverseName); // "ecilA"
Console.WriteLine("Your reverse name is: {0} ", reverseName);
// "Your reverse name is: System.Char[]"
}
In both cases you are actually calling different methods. See Member Overloading
When you call Console.WriteLine(Reversenames) you execute method WriteLine(Char[]), which will convert char array into string.
When you call Console.WriteLine("some text", Reversenames) you execute method WriteLine(String, Object[]), which will call .ToString() on every object given after the placeholder. new char[] {}.ToString() returns exactly what you see "system.char[]"

String to decimal and back

I need to take an input from the user, turn all the chars to their decimal value and display the as one string without spaces, then turn it into a string and display it, and afterwards take the number string and turn back to the original string.
A."Hello World" - string
B."72101108108111 87111114108100" - string
C."7210110810811187111114108100" (Processed and displayed) - int
D."72101108108111 87111114108100" - string
E."Hello World" - string
I got to this stage :
string input = Console.ReadLine();
byte[] array = Encoding.ASCII.GetBytes(input);
It's not much but its my first try at creating a program.
here is a example using decimal. but you could also use System.Numerics.BigInteger with its ToString and Parse functions for bigger numbers
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx
using System;
namespace big_number
{
class Program
{
static void Main(string[] args)
{
decimal d = 0;
begining:
try {d = Convert.ToDecimal(Console.ReadLine()); }//<------ HERE IT IS!!!
catch (Exception EX)// look up what exceptions you want to catch
{
Console.WriteLine("try again\r\n\n" + EX.Message);//display error (if you want)
d = 0;//just incase
goto begining; // do not run this code outside of debugger you may get caught in inifinite loop
}
//and back again
string s = "" + d;
Console.WriteLine(s);//we could just pass d
Console.ReadLine();
}
}
}

How could I create a string with an object value in it?

This questions really isn't hard to understand. I have always wondered this and wondered if possible, how could it be done. Well this is sort what I'd like to do if possible:
int number = 50;
string text = "The number is %number";
Where I wrote %number in the string above, I would like the value of number to be inserted into the string, because the way I would usually go about doing something like this would be like:
int number = 50;
string text = "The number is " + number.ToString();
Which yes, the way I integrated number into the string above is an okay way of doing so, but I have always wondered, is it possible to do something such as the first example I wrote, where to put a value of an object into a string all you would have to do is write some type of character or string (used to reference the object), along with the name of the object into a string to get a result of a string with the value of the object in it? Or is there anything sort of like this you're able to do?
You would use string.Format:
string text = string.Format("The number is {0}", number);
Note that all objects have a ToString method, which means that all objects can be used as arguments to string.Format, however the default response from ToString is to return the full name of the type, which might not make much sense.
For instance, this:
public class Dummy
{
}
var d = new Dummy();
string text = string.Format("The dummy is {0}", d);
will assign something like the following value to text:
"The dummy is Your.Namespace.Dummy";
You have two options:
Override ToString and return something meaningful for your new type
Read off a property or something instead, e.g.:
string text = string.Format("The dummy is {0}", d.SomeProperty);
Also note that string.Format can take multiple arguments:
int a = 10;
int b = 20;
int c = a + b;
string text = string.Format("{0} + {1} = {2}", a, b, c);
There's a lot more to string.Format than what I have shown here, so click the link to the documentation (first line of this answer) to learn more.
You probably need to check Sting.Format
string text = String.Format("The number1 is {0},number2 is {1}", number1, number2);
It is also worth to check this discussion regarding When is it better to use String.Format vs string concatenation?
`

Characters not returning

How to fix the errors with characters in C# Employee class I am making. I know how to handle string, int, and double. The char.Parse doesn't cooperate.
public static string AskForLastName()
{
string inValue;
Console.Write("Enter last name: ");
inValue = Console.ReadLine();
return inValue; //works fine
}
public static char AskForGender()
{
char inValue;
Console.Write("Enter gender: ");
inValue = Console.ReadLine();//error here for some reason
return (char.Parse(inValue));//error here for some reason
}
public static int AskForNoDependendents()
{
string inValue;
Console.Write("Enter the dependents: ");
inValue = Console.ReadLine();
return (int.Parse(inValue));//works fine
}
public static double AskForAnnualSalary()
{
string inValue;
Console.Write("Enter annual salary: ");
inValue = Console.ReadLine();
return (double.Parse(inValue));//works fine
}
Console.ReadLine() returns a string. You can't implicitly convert that to a character- what if someone enters "Male" or " M" (preceded by one or more spaces).
Your AskForGender method is going to need to be smarter about what input it accepts, and how it parses that input.
If you really need a character out of this (to satisfy the assignment, or whatever), then you need to figure out a way to get from all of the possible String inputs ("Male", "MALE", "Female", "Horse", "Dog", "4", etc.) to either:
An acceptable Character (presumably 'M' or 'F', but maybe others?)
or
An error condition, whereupon maybe you print a nice error message and ask them to re-enter?
Description
Console.ReadLine returns a string. You can use string[] to get the first character of your string. But you have to make sure that the user inserts at least one character.
Sample
public static char AskForGender()
{
while (true)
{
Console.Write("Enter gender (m/w): ");
string inValue = Console.ReadLine();
// check that the user inputs a character
if (!string.IsNullOrEmpty(inValue) && (inValue[0] == 'm' || inValue[0] == 'w'))
return inValue[0];
}
}
Update
My sample covers now that the user inputs m or w.
Update
It is homework so...
If your Teacher ask "But what happens if the user inputs a M instead of m? You should say "It asks the user again".
If your Teacher asks then "How to make it possible to accept M and m? You should say i can make it case insensitive.
Sample
You should use i can use .NET's .ToUpper() method.
.ToUpper() - Returns a copy of this string converted to uppercase.
public static char AskForGender()
{
while (true)
{
Console.Write("Enter gender (m/w): ");
string inValue = Console.ReadLine();
// check that the user inputs a character
if (!string.IsNullOrEmpty(inValue) && (inValue.ToUpper()[0] == 'M' || inValue.ToUpper()[0] == 'W'))
return inValue.ToUpper()[0]; // returns M or W
}
}
You're trying to pull a string into a char. Console.ReadLine() returns a string.
If you need specifically one character (Presumably M or F) consider making your inValue a string, trimming it (to ensure there are no leading spaces), and then returning inValue[0] (which should be a char)
Something like:
string inValue = Console.ReadLine();
inValue = inValue.Trim();
return inValue[0];
**Note- that's not the best way to do it, but it should make the idea fairly clear.
According to MSDN ReadLine returns a string - you can't assign a string to a char!

C# 2.0 function which will return the formatted string

I am using C# 2.0 and I have got below type of strings:
string id = "tcm:481-191820"; or "tcm:481-191820-32"; or "tcm:481-191820-8"; or "tcm:481-191820-128";
The last part of string doesn't matter i.e. (-32,-8,-128), whatever the string is it will render below result.
Now, I need to write one function which will take above string as input. something like below and will output as "tcm:0-481-1"
public static string GetPublicationID(string id)
{
//this function will return as below output
return "tcm:0-481-1"
}
Please suggest!!
If final "-1" is static you could use:
public static string GetPublicationID(string id)
{
int a = 1 + id.IndexOf(':');
string first = id.Substring(0, a);
string second = id.Substring(a, id.IndexOf('-') - a);
return String.Format("{0}0-{1}-1", first, second);
}
or if "-1" is first part of next token, try this
public static string GetPublicationID(string id)
{
int a = 1 + id.IndexOf(':');
string first = id.Substring(0, a);
string second = id.Substring(a, id.IndexOf('-') - a + 2);
return String.Format("{0}0-{1}", first, second);
}
This syntax works even for different length patterns, assuming that your string is
first_part:second_part-anything_else
All you need is:
string.Format("{0}0-{1}", id.Substring(0,4), id.Substring(4,5));
This just uses substring to get the first four characters and then the next five and put them into the format with the 0- in there.
This does assume that your format is a fixed number of characters in each position (which it is in your example). If the string might be abcd:4812... then you will have to modify it slightly to pick up the right length of strings. See Marco's answer for that technique. I'd advise using his if you need the variable length and mine if the lengths stay the same.
Also as an additional note your original function of returning a static string does work for all of those examples you provided. I have assumed there are other numbers visible but if it is only the suffix that changes then you could happily use a static string (at which point declaring a constant or something rather than using a method would probably work better).
Obligatory Regular Expression Answer:
using System.Text.RegularExpressions;
public static string GetPublicationID(string id)
{
Match m = RegEx.Match(#"tcm:([\d]+-[\d]{1})", id);
if(m.Success)
return string.Format("tcm:0-{0}", m.Groups[1].Captures[0].Value.ToString());
else
return string.Empty;
}
Regex regxMatch = new Regex("(?<prefix>tcm:)(?<id>\\d+-\\d)(?<suffix>.)*",RegexOptions.Singleline|RegexOptions.Compiled);
string regxReplace = "${prefix}0-${id}";
string GetPublicationID(string input) {
return regxMatch.Replace(input, regxReplace);
}
string test = "tcm:481-191820-128";
stirng result = GetPublicationID(test);
//result: tcm:0-481-1

Categories

Resources