Update string with interpolation for each using - c#

I have code like this:
int i = 1;
string dynemicString = $"i = {i}";
while(i<10)
{
Console.WriteLine(i);
i++;
}
And I want to get result like this:
i = 1
i = 2
i = 3
...
How to do it?

int i = 1;
while(i<10)
{
Console.WriteLine($"i = {i}");
i++;
}
For more information read about String Interpolation
If you want a more tokenized way of doing this, use String.Format
int i = 1;
string dynemicString = "i = {0}";
while(i<10)
{
Console.WriteLine(string.Format(dynemicString,i));
i++;
}

Here's an alternative approach to TheGeneral's answer. I'm not suggesting using it, but I find it an "interesting" idea just for the sake of learning a bit more about how string interpolation works.
When an interpolated string literal is converted to a string, all the expressions are immediately evaluated and the string is formatted. The string can't change afterwards.
When an interpolated string literal is converted to a FormattableString, the expressions are evaluated, but the string formatting isn't performed. Instead, the results of all the expressions are stored for later formatting. Every time you call ToString on a FormattableString, the formatting is performed again.
So, we can make it dynamic by making the same values (as evaluated initially) return different strings when string formatting happens. One simple - but really ugly - way of doing that is to use a delegate to capture i, and then put the delegate in a wrapper that overrides ToString and executes the delegate each time. Here's a complete example of that:
// CODE FOR EDUCATIONAL PURPOSES ONLY. DON'T USE IN PRODUCTION!
using System;
public class FuncWrapper
{
private readonly Func<string> func;
public FuncWrapper(Func<string> func) =>
this.func = func;
public override string ToString() => func();
}
class Test
{
static void Main()
{
int i = 1;
// Capture i in a delegate; each time the delegate
// is executed, you'll get a different value. Each
// time ToString is called, the delegate will be called
var wrapper = new FuncWrapper(() => i.ToString());
FormattableString dynamicString = $"i = {wrapper}";
while (i < 10)
{
Console.WriteLine(dynamicString);
i++;
}
}
}
Output:
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9

Related

How to parse a string and a bool array to a method, modifying the string in the method and verifying that the string fulfills all conditions in C#?

I've been doing C# now for about two months. And I want to create a method that does the following:
Takes a string.
Takes an array with conditions that needs to be applied to the string.
Modifies the string within the called method.
Checks if the modified string fulfills all boolean conditions.
Then "returns"(using the ref) string to the caller method.
So for example, if I wanted the user to input their first and last name. I'd do:
GetStringLine(out string name, new bool[] { name.Length > 1, name.Split(' ').Length > 1})
I've been trying several different ways at this point, I believe I am simply missing something. It feels like there should be some way to tell the method that the bool condition being passed into the method should be applied to the actively modified string.
Anyways, as I don't have a whole lot of experience with C#, or programming, I am hoping that the following code block will explain or hint further to what I am trying to achieve. Really hoping to get some more understanding of this. So keep in mind, I don't need to do it exactly as I am showing, if there would be a another way of accomplishing my goals, I'd be happy to do that instead.
Best regards!
static void Main(string[] args) {
string str = "test";
GetStringLine(ref str,
new bool[] {
str.Length > 1,
str.Length < 3
}
);
}
public static void GetStringLine(ref string str, bool[] conditions) {
while (!conditions.All(condition => condition)) {
str = Console.ReadLine();
Console.WriteLine("");
}
}
Edit:
After #pm100 's solution, I applied it as such and it works as expected:
public static void GetStringLine(out string output, Predicate<string>[] conditions) {
string input = "";
while (!conditions.All(condition => condition(input))) {
input = Console.ReadLine();
Console.WriteLine("");
}
output = input;
}
Although, I feel like it's a bit abundant due to the string input = "" and output = input. My first attempt was to do it like this:
public static void GetStringLine(out string output, Predicate<string>[] conditions) {
while (!conditions.All(condition => condition(output))) {
output = Console.ReadLine();
Console.WriteLine("");
}
}
Sadly, this yields me naught but two errors:
First:
CS1628 Cannot use ref, out, or in parameter 'output' inside an anonymous method,
lambda expression, query expression, or local function
Second:
CS0177 The out parameter 'output' must be assigned to before control
leaves the current method
I'll add that my actual code contains more fluff, I.e. error prompts and other things that are needed, but I deemed it not relevant to the current question at hand.
I leave out the looping to reprompt and just show the check against arbitrary conditions (since thats the tricky bit)
static bool CheckString(string input, Predicate<string>[] conditions) {
conditions.All(c => c(input))
}
now to use
var conditions = new Predicate<string>[] {
(s)=>s.Length > 3,
(s)=>s.Contains("a")
};
CheckString("abcdef", conditions); // true
CheckString("ab", conditions); // false
the hard part for you will be to tell the user on each reprompt what the conditions are. You cannot (easily) get a string representation of the predicates, probably should pass in a prompt string
Like this
static string ReadCheckedString(string prompt, Predicate<string>[] conditions) {
while (true) {
Console.WriteLine(prompt);
var input = Console.ReadLine();
if (input == null || input.Length == 0)
return null;
if (conditions.All(c => c(input))) {
return input;
}
}
}
and
var conditions = new Predicate<string>[] {
(s)=>s.Length > 3,
(s)=>s.Contains("a")
};
var ans = ReadCheckedString("longer than 3 chars and contains 'a'", conditions);

Use null-conditional operator to set value to 0 if null

I'm new to C# but not to programming in general.
I am trying to set add some error checking to my program. There are 3 textboxes and I am trying to make it so that if the text box is left blank, it assumes a value of 0. Here is my code so far:
private void btnCalculate_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(txtNumberOfClassATix.Text)) // Assumes 0 if no number entered for txtNumberOfClassATix.Text.
{
txtNumberOfClassATix.Text = "0";
}
if (String.IsNullOrEmpty(txtNumberOfClassBTix.Text)) // Assumes 0 if no number entered for txtNumberOfClassBTix.Text.
{
txtNumberOfClassBTix.Text = "0";
}
if (String.IsNullOrEmpty(txtNumberOfClassCTix.Text)) // Assumes 0 if no number entered for txtNumberOfClassCTix.Text.
{
txtNumberOfClassCTix.Text = "0";
}
int classANum = int.Parse(txtNumberOfClassATix.Text);
int classBNum = int.Parse(txtNumberOfClassBTix.Text);
int classCNum = int.Parse(txtNumberOfClassCTix.Text);
double classATotal = classANum * classAPrice;
double classBTotal = classBNum * classBPrice;
double classCTotal = classCNum * classCPrice;
lblCalculatedClassARevenue.Text = $"{classATotal:c}";
lblCalculatedClassBRevenue.Text = $"{classBTotal:c}";
lblCalculatedClassCRevenue.Text = $"{classCTotal:c}";
lblCalculatedTotalRevenue.Text = $"{(classATotal + classBTotal) + classCTotal:c}";
}
This code works but I'm sure I could replace those if statements with something simpler. I've seen how to set a variable to null if another is null using the null-conditional operator but I don't really grasp it enough to adapt it to my scenario.
So far maccettura's answer is the best, but can we do better? Sure we can. Let's make a general-purpose extension method:
internal static class Extensions
{
public static int? AsInt(this string s)
{
int result;
if (s == null)
return null;
else if (int.TryParse(s, out result))
return result;
else
return null;
}
}
And now:
int classANum = txtNumberOfClassATix.Text.AsInt() ?? 0;
If it's an int, you get the int. If it's not, you get zero. Easy peasy.
Or, you might want this extension method:
internal static class Extensions
{
public static int AsInt(this string s, int default = 0)
{
int result;
if (s == null)
return default;
else if (int.TryParse(s, out result))
return result;
else
return default;
}
}
And now you can say what you want the default to be without using ??.
This style of programming is called "fluent programming"; it can make code that is very easy to read and understand.
Notice that this solution does not update the UI with zeros; if you wanted to do that then I would recommend splitting that into two steps: one which causes the mutation, and then a separate step which computes the value. Operations which are useful for both their effects and their values can be confusing.
This is a perfect time to use a method so you arent repeating yourself:
private static int GetInputAsInt(TextBox textbox)
{
int outputValue = 0;
if(textbox?.Text != null && int.TryParse(textbox.Text, out outputValue))
{
return outputValue;
}
return 0;
}
Now you are checking if the textbox itself is not null, and that the value contained therein is a int, if anything fails it returns a 0;
Call it in your other method like this:
int classANum = GetInputAsInt(txtNumberOfClassATix);
Which means your button click event would be a bit simpler:
private void btnCalculate_Click(object sender, EventArgs e)
{
int classANum = GetInputAsInt(txtNumberOfClassATix);
int classBNum = GetInputAsInt(txtNumberOfClassBTix);
int classCNum = GetInputAsInt(txtNumberOfClassCTix);
double classATotal = classANum * classAPrice;
double classBTotal = classBNum * classBPrice;
double classCTotal = classCNum * classCPrice;
lblCalculatedClassARevenue.Text = $"{classATotal:c}";
lblCalculatedClassBRevenue.Text = $"{classBTotal:c}";
lblCalculatedClassCRevenue.Text = $"{classCTotal:c}";
lblCalculatedTotalRevenue.Text = $"{(classATotal + classBTotal) + classCTotal:c}";
}
To keep it simple, a good approach is to use the conditional operator. The full example is below (broken across two lines for readability):
txtNumberOfClassATix.Text =
String.IsNullOrEmpty(txtNumberOfClassATix.Text) ? "0" : txtNumberOfClassATix.Text;
This is a nice, readable, assignment for the first part:
myString = ...
The conditional operator breaks down by providing a boolean expression (true/ false) on the left side of the ?. So, for example:
myString = anotherString == "" ? ... // checking if another string is empty
The final part is the :. To the left is the assignment if the expression is true, and to the right goes the assignment if the expression is false. To finish the example:
myString = anotherString == "" ? "anotherString is empty" : "anotherString is not empty";
The above example can be written out in full to clear up any misunderstanding as:
if (anotherString == "")
{
myString = "anotherString is empty";
}
else
{
myString = "anotherString is not empty";
}
This can apply to all the statements. The documentation is found here.
The best way to reduce the line of code is use the function for your common operation(s). In your case, you can create function which checks whether or not the object is NULL or empty. Based on the return value of that function you can proceed ahead. On the other hand, you can handle it on front-end by using different validators such as RequiredFieldValidator, CustomValidator, etc.

First char of string to upper case: what is more costly to the server? C#

I have two ways to get the first letter of a string to upper case, but I would like to know which one uses more server resources?
(MVC 5, C#)
string test1 = test.ToUpper()[0] + test.Substring(1);
or
string test1 = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test.ToLower());
Add this to your ExtensionMethods.cs
public static class ExtensionMethods
{
public static string UppercaseFirstLetter(this string value)
{
//
// Uppercase the first letter in the string this extension is called on.
//
if (value.Length > 0)
{
char[] array = value.ToCharArray();
array[0] = char.ToUpper(array[0]);
return new string(array);
}
return value;
}
}
According to : http://www.dotnetperls.com/uppercase-first-letter it is faster than your first method because because it only allocates one new string in the return statement. The first approach allocates two strings: the Substring(1), and then a new string with string.Concat.
I made a dotnetfiddle which tests the performance of the two methods you mentioned, plus the one suggested by SatuDuaTiga.
https://dotnetfiddle.net/VyNjht
The method suggested by SatuDuaTiga seems to outperform the first method by a small margin, but using .ToTitleCase() in the CultureInfo namespace is by far the worst.
Average results of multiple runs:
Method 1: 93673 ticks
Method 2: 260491 ticks
Method 3: 90649 ticks
You can disassemble the TextInfo class and view the source of the .ToTitleCase() method and you'll see it's doing a lot of stuff.
Well I did a small benchmarking to check it out and there is no such observable difference present between the two approaches. You can use the below code to perform the same at your end. Try, running it multiple times as suggested by #ta.speot.is in below comment.
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Benchmark();
Console.WriteLine();
}
}
static void Benchmark()
{
string test = "rahul";
Stopwatch watch = Stopwatch.StartNew();
string test1 = test.ToUpper()[0] + test.Substring(1);
watch.Stop();
Console.WriteLine(watch.ElapsedTicks);
watch.Restart();
string test2 =
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test.ToLower());
watch.Stop();
Console.WriteLine(watch.ElapsedTicks);
}
If you run it multiple times then it looks like first approach it bit faster than the second one. I tried it for 5 times and below goes the result
4
5
2
4
2
3
2
3

Best solution for an StringToInt function in C#

I were asked to do an StringToInt / Int.parse function on the white board in an job interview last week and did not perform very good but I came up with some sort of solution. Later when back home I made one in Visual Studion and I wonder if there are any better solution than mine below.
Have not bothred with any more error handling except checking that the string only contains digits.
private int StrToInt(string tmpString)
{
int tmpResult = 0;
System.Text.Encoding ascii = System.Text.Encoding.ASCII;
byte[] tmpByte = ascii.GetBytes(tmpString);
for (int i = 0; i <= tmpString.Length-1; i++)
{
// Check whatever the Character is an valid digit
if (tmpByte[i] > 47 && tmpByte[i] <= 58)
// Here I'm using the lenght-1 of the string to set the power and multiply this to the value
tmpResult += (tmpByte[i] - 48) * ((int)Math.Pow(10, (tmpString.Length-i)-1));
else
throw new Exception("Non valid character in string");
}
return tmpResult;
}
I'll take a contrarian approach.
public int? ToInt(this string mightBeInt)
{
int convertedInt;
if (int.TryParse(mightBeInt, out convertedInt))
{
return convertedInt;
}
return null;
}
After being told that this wasn't the point of the question, I'd argue that the question tests C coding skills, not C#. I'd further argue that treating strings as arrays of characters is a very bad habit in .NET, because strings are unicode, and in any application that might be globalized, making any assumption at all about character representations will get you in trouble, sooner or later. Further, the framework already provides a conversion method, and it will be more efficient and reliable than anything a developer would toss off in such a hurry. It's always a bad idea to re-invent framework functionality.
Then I would point out that by writing an extension method, I've created a very useful extension to the string class, something that I would actually use in production code.
If that argument loses me the job, I probably wouldn't want to work there anyway.
EDIT: As a couple of people have pointed out, I missed the "out" keyword in TryParse. Fixed.
Converting to a byte array is unnecessary, because a string is already an array of chars. Also, magic numbers such as 48 should be avoided in favor of readable constants such as '0'. Here's how I'd do it:
int result = 0;
for (int i = str.Length - 1, factor = 1; i >= 0; i--, factor *= 10)
result += (str[i] - '0') * factor;
For each character (starting from the end), add its numeric value times the correct power of 10 to the result. The power of 10 is calculated by multiplying it with 10 repeatedly, instead of unnecessarily using Math.Pow.
I think your solution is reasonably ok, but instead of doing math.pow, I would do:
tmpResult = 10 * tmpResult + (tmpByte[i] - 48);
Also, check the length against the length of tmpByte rather than tmpString. Not that it normally should matter, but it is rather odd to loop over one array while checking the length of another.
And, you could replace the for loop with a foreach statement.
If you want a simple non-framework using implementation, how 'bout this:
"1234".Aggregate(0, (s,c)=> c-'0'+10*s)
...and a note that you'd better be sure that the string consists solely of decimal digits before using this method.
Alternately, use an int? as the aggregate value to deal with error handling:
"12x34".Aggregate((int?)0, (s,c)=> c>='0'&&c<='9' ? c-'0'+10*s : null)
...this time with the note that empty strings evaluate to 0, which may not be most appropriate behavior - and no range checking or negative numbers are supported; both of which aren't hard to add but require unpretty looking wordy code :-).
Obviously, in practice you'd just use the built-in parsing methods. I actually use the following extension method and a bunch of nearly identical siblings in real projects:
public static int? ParseAsInt32(this string s, NumberStyles style, IFormatProvider provider) {
int val;
if (int.TryParse(s, style, provider, out val)) return val;
else return null;
}
Though this could be expressed slightly shorter using the ternary ? : operator doing so would mean relying on side-effects within an expression, which isn't a boon to readability in my experience.
Just because i like Linq:
string t = "1234";
var result = t.Select((c, i) => (c - '0') * Math.Pow(10, t.Length - i - 1)).Sum();
I agree with Cyclon Cat, they probably want someone who will utilize existing functionality.
But I would write the method a little bit different.
public int? ToInt(this string mightBeInt)
{
int number = 0;
if (Int32.TryParse(mightBeInt, out number))
return number;
return null;
}
Int32.TryParse does not allow properties to be given as out parameter.
I was asked this question over 9000 times on interviews :) This version is capable of handling negative numbers and handles other conditions very well:
public static int ToInt(string s)
{
bool isNegative = false, gotAnyDigit = false;
int result = 0;
foreach (var ch in s ?? "")
{
if(ch == '-' && !(gotAnyDigit || isNegative))
{
isNegative = true;
}
else if(char.IsDigit(ch))
{
result = result*10 + (ch - '0');
gotAnyDigit = true;
}
else
{
throw new ArgumentException("Not a number");
}
}
if (!gotAnyDigit)
throw new ArgumentException("Not a number");
return isNegative ? -result : result;
}
and a couple of lazy tests:
[TestFixture]
public class Tests
{
[Test]
public void CommonCases()
{
foreach (var sample in new[]
{
new {e = 123, s = "123"},
new {e = 110, s = "000110"},
new {e = -011000, s = "-011000"},
new {e = 0, s = "0"},
new {e = 1, s = "1"},
new {e = -2, s = "-2"},
new {e = -12223, s = "-12223"},
new {e = int.MaxValue, s = int.MaxValue.ToString()},
new {e = int.MinValue, s = int.MinValue.ToString()}
})
{
Assert.AreEqual(sample.e, Impl.ToInt(sample.s));
}
}
[Test]
public void BadCases()
{
var samples = new[] { "1231a", null, "", "a", "-a", "-", "12-23", "--1" };
var errCount = 0;
foreach (var sample in samples)
{
try
{
Impl.ToInt(sample);
}
catch(ArgumentException)
{
errCount++;
}
}
Assert.AreEqual(samples.Length, errCount);
}
}

How should I convert a number with a text suffix to an integer in c#?

What's the cleanest/best way in C# to convert something like 400AMP or 6M to an integer? I won't always know what the suffix is, and I just want whatever it is to go away and leave me with the number.
You could use a regular expression:
Regex reg = new Regex("[0-9]*");
int result = Convert.ToInt32(reg.Match(input));
Okay, here's a long-winded solution which should be reasonably fast. It's similar to Guffa's middle answer, but I've put the conditions inside the body of the loop as I think that's simpler (and allows us to fetch the character just once). It's a matter of personal taste really.
It deliberately doesn't limit the number of digits that it matches, because if the string is an integer which overflows Int32, I think I'd rather see an exception than just a large integer :)
Note that this also handles negative numbers, which I don't think any of the other solutions so far do...
using System;
class Test
{
static void Main()
{
Console.WriteLine(ParseLeadingInt32("-1234AMP"));
Console.WriteLine(ParseLeadingInt32("+1234AMP"));
Console.WriteLine(ParseLeadingInt32("1234AMP"));
Console.WriteLine(ParseLeadingInt32("-1234"));
Console.WriteLine(ParseLeadingInt32("+1234"));
Console.WriteLine(ParseLeadingInt32("1234"));
}
static int ParseLeadingInt32(string text)
{
// Declared before loop because we need the
// final value
int i;
for (i=0; i < text.Length; i++)
{
char c = text[i];
if (i==0 && (c=='-' || c=='+'))
{
continue;
}
if (char.IsDigit(c))
{
continue;
}
break;
}
return int.Parse(text.Substring(0, i));
}
}
It's possibly not the cleanest method, but it's reasonably simple (a one liner) and I would imagine faster than a regex (uncompiled, for sure).
var str = "400AMP";
var num = Convert.ToInt32(str.Substring(0, str.ToCharArray().TakeWhile(
c => char.IsDigit(c)).Count()));
Or as an extension method:
public static int GetInteger(this string value)
{
return Convert.ToInt32(str.Substring(0, str.ToCharArray().TakeWhile(
c => char.IsDigit(c)).Count()));
}
Equivalently, you could construct the numeric string from the result of the TakeWhile function, as such:
public static int GetInteger(this string value)
{
return new string(str.ToCharArray().TakeWhile(
c => char.IsNumber(c)).ToArray());
}
Haven't benchmarked them, so I wouldn't know which is quicker (though I'd very much suspect the first). If you wanted to get better performance, you would just convert the LINQ (extension method calls on enumerables) to a for loop.
Hope that helps.
There are several options...
Like using a regular expression:
int result = int.Parse(Regex.Match(input, #"^\d+").Groups[0].Value);
Among the fastest; simply looping to find digits:
int i = 0;
while (i < input.Length && Char.IsDigit(input, i)) i++;
int result = int.Parse(input.Substring(0, i));
Use LastIndexOfAny to find the last digit:
int i = input.LastIndexOfAny("0123456789".ToCharArray()) + 1;
int result = int.Parse(input.Substring(0, i));
(Note: breaks with strings that has digits after the suffix, like "123asdf123".)
Probably fastest; parse it yourself:
int i = 0;
int result = 0;
while (i < input.Length) {
char c = input[i];
if (!Char.IsDigit(c)) break;
result *= 10;
result += c - '0';
i++;
}
If all you want to do is remove an unknown postfix from what would otherwise be an int, here is how I would do it:
I like a utility static method I call IsInt(string possibleInt) which will, as the name implies, return True if the string will parse into an int. You could write this same static method into your utility class (if it's not there already) and try:
`string foo = "12345SomePostFix";
while (!Tools.ToolBox.IsInt(foo))
{
foo = foo.Remove(foo.Length - 1);
}
int fooInt = int.Parse(foo);`

Categories