Is it possible to define a default number format that is used whenever I convert an integer (or double etc.) to a String without specifying a format string?
C# example:
int i = 123456;
string s = "Hello " + i;
// or alternatively with string.Format without format definition
string s = string.Format("Hello {0}", i);
ASP.NET Razor example:
<div>
Hello #i
</div>
I think all these code lines implicitly use the default ToString() method for Int32. And not surprisingly, all these code lines result in "Hello 123456", but I want "Hello 123,456".
So can I specify that "N0" should be used by default (at least for integer)?
I already found the question Set Default DateTime Format c# - it looked good, but it doesn't help me for numbers.
Edit: I'm aware that I could write an extension method which I can use throughout my application, but this is not what I'm looking for. I would like to find a property (maybe somewhere hidden in CultureInfo or NumberFormatInfo) which is currently set to "G" and is used by the default Int32.ToString() implementation.
If you create your own CultureInfo and you can alter it and then assign it to CultureInfo.CurrentCulture like in this answer:
https://stackoverflow.com/a/24785761/166921
You Can override systems toString() method into your class as under:
public override string ToString()
{
int i = 123456;
string s = "Hello " + i;
return string.Format("Hello {0}", i);
}
you can use extension methods
public static class MyExtensions
{
public static string ToDefaultFormatString(this int i)
{
//Staf
}
}
and your code look like
int i = 123456;
string s = "Hello " + i.ToDefaultFormatString();
As you are trying to modify the functionality for a primitive type, which has no class, you cannot override the ToString() method.
You can however create an extension method.
namespace System
{
public class IntExt
{
public string ToStringN0(this int i)
{
return i.ToString("N0");
}
}
}
and then use by
int i = 5000;
Console.WriteLine(i.ToStringN0());
The example puts the class in the System namespace so it will be available through the application.
This maybe help you :
Decimal.ToString Method (String) MSDN
Double.ToString Method (String) MSDN
asp.net mvc set number format default decimal thousands separators
Related
I have a class with List
public class PolynomialCoefficients<T> : IEnumerable<T>
{
private List<T> coefficients;
public string ToString(string format)
{
StringBuilder polynomialString = new StringBuilder();
char separator = ':';
foreach(T coefficient in coefficients)
{
polynomialString.Append(String.Format("0.0000", coefficient.ToString()));
polynomialString.Append(separator);
}
polynomialString.Remove(polynomialString.Length - 1, 1);
return polynomialString.ToString();
}
}
Lets say that list contains elements: 1,2,3
I want to call
ToString("0.000")
and get output: 1.000:2.000:3.000
but every time output is similar to 0.000:0.000:0.000
String.Format needs a very specific kind of string. You gave it a literal string to print:
String.Format("0.0000", coefficient.ToString());
So it just printed it. If you had given it a placeholder:
String.Format("{0}", coefficient.ToString("0.0000"));
It would have substituted the passed argument in. You can also specify the format of the placeholder:
String.Format("{0:f4}", coefficient);
"f4" would give you your format. The standard formatting strings can be found on MSDN
First, you don't need a ToString() call on the coefficient.ToString(). Second, your format string is a bit incorrect: you need to use the "{0:0.0000}" form.
And while we're at it, your code can be greatly simplified:
var result = string.Join(";", coefficients.Select(c => string.Format("{0:0.0000}", c));
return result;
public class PolynomialCoefficients<T> : IEnumerable<T>
{
private List<T> coefficients;
public string ToString(string format)
{
const string separator = ":";
return string.Join(separator, coefficients.Select(c => string.Format("{0:f4}", c)));
}
}
The reason is because of call to ToString in String.Format and not specifying the place holder.
String.Format("0.0000", coefficient.ToString())
//^^^^^
String.Format with your format should expect a floating point number, it will not work on string values, for string values, format would be ignored and passed value will be returned.
Also you have to specify the place holder like:
string str = (String.Format("{0:0.0000}", coefficient));
Consider the following example:
String.Format("{0:0.0000}", 1.2345123123) //would return "1.2345"
String.Format("{0:0.0000}", "1.2345123123")//would return "1.2345123123" ignoring the format
You should constrain T to IFormattable:
public class PolynomialCoefficients<T> : IEnumerable<T>
where T : IFormattable
With that you can use coefficient.ToString("0.0000", null) where coefficient is a T. You can also use:
polynomialString.AppendFormat("{0:0.0000}", coefficient)
with your StringBuilder. That will end up calling coefficient.ToString("0.0000", null) as well.
Is there a format string for the C# string.Format method that picks a substring from the corresponding argument? Like so:
var lang1 = "EN";
var lang2 = "FR";
var shortFormat = "Foo-{0:0-0}.pdf";
var longFormat = "Foo-{0:0-1}.pdf";
string.Format(shortFormat, lang1) // Foo-E.pdf
string.Format(shortFormat, lang2) // Foo-F.pdf
string.Format(longFormat, lang1) // Foo-EN.pdf
string.Format(longFormat, lang2) // Foo-FR.pdf
To anticipate a few comments: Yes, I know the Substring method. I have also read that string.Format is slower than a simple Substring. The example above is heavily simplified. Imagine that the string.Format statement resides in one place, while the lang1/lang2 argument is an input from another place and the shortFormat/longFormat is defined in a resx file.
That is, in the place where the format is to be defined we don't know anything about the value being formatted (lang1/lang2 in the example) nor do we have any means to execute C# code. Hence we can't call any method such as Substring on the value. At the place where the formatting code runs, in turn, we take the format as a parameter, so we can't simply perform a Substring on the value because we don't know whether the format requires it or not (except if we inspect the format).
No, the string.Format does not have this feature, which is better explained here: Can maximum number of characters be defined in C# format strings like in C printf?
If you don't want to use Substring I would create an extension class for string like this: http://msdn.microsoft.com/en-us/library/bb311042.aspx
namespace CustomExtensions
{
public static class StringExtension
{
public static string ShortFormat(this string str)
{
// manipulate and return str here
}
public static string LongFormat(this string str)
{
// manipulate and return str here
}
}
}
XSLT formatting can be an option: user gets ability to provide almost everything in configuration file and even execute custom c# code in your domain if it is required.
Please also consider that changes of format can be restricted to relatively small amount of actions: crop, pad or insert one or two things in some positions. Each one can be set as individual function and provided with own parameters.
There are two ways to provide custom formatting. You can either implement IFormattable on a custom type to control how that type is always formatted, or implement IFormatProvider to override how other types are formatted in specific cases.
In your case I would suggest creating a new type to encapsulate how your software deals with language codes;
public struct LanguageCode : IFormattable {
public readonly string Code;
public LanguageCode(string code) {
Code = code;
}
public override string ToString()
=> this.ToString("L", CultureInfo.CurrentCulture);
public string ToString(string format)
=> this.ToString(format, CultureInfo.CurrentCulture);
public string ToString(string format, IFormatProvider provider){
if (String.IsNullOrEmpty(format))
format = "L";
if (provider == null)
provider = CultureInfo.CurrentCulture;
switch (format.ToUpperInvariant()){
case "L": // Long
return Code.ToString(provider);
case "S": // Short
return Code.SubString(0,1).ToString(provider);
default:
throw new FormatException($"The {format} format string is not supported.");
}
}
public static implicit operator LanguageCode(string code)
=> new LanguageCode(code);
public static implicit operator string(LanguageCode language)
=> language.Code;
}
Then from your example;
var lang1 = (LanguageCode)"EN";
LanguageCode lang2 = "FR";
var shortFormat = "Foo-{0:S}.pdf";
var longFormat = "Foo-{0:L}.pdf";
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?
`
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
Is there any way to make
TypeDescriptor.GetConverter.ConvertFromString convert to DateTime using a custom format e.g. "2011-04-21 13-03-56"?
If not, is there any DateTime-format out there that can be applied to a folder name (/,\,:,etc. are not allowed as you know)?
Help is very much appreciated. Thanks in advance
Random-I-Am
Edit:
Since my request still seems to not be understood correctly I am again trying to elaborate on my question. My users are creating folders with specific names. For example "1000_Link_Topic1_2011-01-25 14-12-10". They are free to combine their information as they like and omit information where needed. They don't even have to care about case sensitivity. So I could face another folder named "1000_link_Topic2".
What I have is a single class with a single property for each possible fragment of information. In this case I would have (Since I had to find a way of checking each properties default value regardless of the property type I am using nullable types):
Short? short_val;
EContentType? enum_val;
String string_val;
DateTime? datetime_val;
My code obviously splits the folder name at "_" and then tells for each fragment to which of the above property types it belongs. As soon as I know the corresponding type I am trying to convert to the Type, lets say t, using TypeDescriptor.GetConverter(t).ConvertFromString(info_frag[i]). I hope you now understand why I cannot use another conversion Method.
The code works for all the types mentioned above. My problem is to find a custom DateTime format that can be used on a folder name. All of the formats I know are using colons to separate hours from minutes and seconds.
What I want is a way to convert from a custom DateTime-format to a DateTime-object using TypeDescriptor.GetConverter.ConvertFromString. If that is not possible I either need to find a standard DateTime-format which can be assigned as a folder name without any further conversion or somehow extend the built-in DateTime-formats by my custom format. If it is going to be the latter I do not care about being able to use seconds or minutes. Hours will do the job.
Thanks again for being as patient as you are and helping me out with this one. Feel free to ask as many further questions as you like. I hope you can help me getting this one to work.
Random-I-Am
I have looked into your problem a little and found that the standard DateTimeTypeConverter uses DateTime.Parse internally which doesn't listen to CurrentCulture info at all. Instead you can trick the conversion process with your own TypeConverter!
I do not know how to attach the new typeconverter to the existing DateTime structure, if you even can, so I made a miniture AdvancedDateTime structure .. which is empty. Noone said your custom TypeConvert should even return such a thing! This one returns a regular DateTime. I provided the code below:
public class CustomDateTimeTypeConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return DateTime.ParseExact(value.ToString(), "yyyy-MM-dd HH-mm-ss", culture);
}
}
[TypeConverter(typeof(CustomDateTimeTypeConverter))]
struct AdvancedDateTime
{
}
[TestFixture]
public class DateTime
{
[Test]
public void TypeConvert_StrangeFormat_ConvertsWithoutProblem()
{
string datetime = "2011-04-21 23-12-13";
TypeConverter converter = TypeDescriptor.GetConverter( typeof (AdvancedDateTime) );
var convertedFromString = converter.ConvertFromString(datetime);
Assert.AreEqual(new DateTime(2011,4,21, 23,12,13), convertedFromString);
}
}
Try this
string m_strDate = DateTime.Now.ToString("MM/dd/yyyy");
m_strDate = m_strDate.Replace("/", "");
Append this m_strDate to your folder
A sample i used for text file is as follows
strPath += "/FileHeader_" + m_strDate + ".txt";
Check this sample
DateTime dt=new DateTime(1990,5,6);
Console.WriteLine(TypeDescriptor.GetConverter(dt).ConvertTo(dt, typeof(string)));
string myStr="1991-10-10";
Console.WriteLine(TypeDescriptor.GetConverter(dt).ConvertFrom(myStr));
The sample code i written just to display as per you need try as per your requirement
string s = "Folder";
DateTime dt = new DateTime(1990, 5, 6);
string str = TypeDescriptor.GetConverter(dt).ConvertTo(dt, typeof(string)).ToString();
string myStr = "1991-10-10";
string str1 = TypeDescriptor.GetConverter(dt).ConvertFrom(myStr).ToString();
s = s + str1.Replace("/", "").Replace(":", "");
textBox1.Text = s;