Spaces in C# Enums - c#

Is there any way to put spaces in a C# enum constant? I've read that you can do it in VB by doing this:
Public Enum EnumWithSpaces
ConstantWithoutSpaces
[Constant With Spaces]
End Enum
...and then access it like this:
Public Sub UsingEnumWithSpaces()
Dim foo As EnumWithSpaces = EnumWithSpaces.[Constant With Spaces]
End Sub
That implies to me that the CLR can handle an enum with spaces.
Is there any way to do this in C#?

This blog post might help you:
http://blog.spontaneouspublicity.com/2008/01/17/associating-strings-with-enums-in-c/
From the article:
But enums can't have spaces in C#!"
you say. Well, I like to use the
System.ComponentModel.DescriptionAttribute
to add a more friendly description to
the enum values. The example enum can
be rewritten like this:
public enum States
{
California,
[Description("New Mexico")]
NewMexico,
[Description("New York")]
NewYork,
[Description("South Carolina")]
SouthCarolina,
Tennessee,
Washington
}
Notice that I do not put descriptions on items where the ToString() version of that item displays just fine.

CLR can handle absolutely any character in identifiers. However, C# restricts the identifier characters to those legal under the CLS, which space isn't. Same goes for VB.NET, by the way - spaces inside square brackets used to work in VB6, but they don't in VB.NET.

If you're working with Visual C# 3.0 or above I've found it convenient to just extend the enum class and use a regex to inset spaces where neccessary:
public static class EnumExtension
{
public static String ToDisplayString(this Enum e)
{
Regex regex = new Regex(#"([^\^])([A-Z][a-z$])");
return regex.Replace(e.ToString(), new MatchEvaluator(m =>
{
return String.Format("{0} {1}", m.Groups[1].Value, m.Groups[2].Value);
}));
}
}
Notice this allows you to work with any enum as is without adding descriptions to every value.
String enumWithSpaces = MessageBoxButtons.OKCancel.ToDisplayString();

Related

I have an Attribute called "public" and i have to access it [duplicate]

a bit of an unusual one.. but I was wondering if anyone knew how I could declare a reserved word as a variable. I have the following code, but it does not like my use of the long variable name. I know I could rename it, but for instrest sakes I would like to know if this is at all possible.
private string lat;
private string long;
public string Lat
{
get
{
return lat;
}
}
public string Long
{
get
{
return long;
}
}
Yes, you can if you really want to:
private string #long;
The actual name of the variable (as reported by reflection etc) is just long; the # sign tells the compiler to ignore the fact that it's also a keyword.
I would very strongly advise against this, however.
As others have mentioned, you can escape a reserved word with #.
In your example you don't really need to, I would write the property like this:
private string _long;
public string Long
{
get
{
return _long;
}
}
And the underscore and the capital L make it compile.
But it's kind of a tradition to call them Lat and Lon, or even better: Latitude and Longitude.
Yes, you can. Using the # symbol.
This will work, for example: private string #long;
Doing this is highly not recommended, but it is possible.
Not an answer I know as I would steer clear of using reserved words as variable names, but if you insist then at least use the following:
private string lat;
private string #long;
public string Lat
{
get
{
return this.lat;
}
}
public string Long
{
get
{
return this.long;
}
}
I may be late to this party, but I thought I would throw in another place where using a reserved word as a variable name is a good idea!!
I am writing a web control, where I want one of the properties to be "class" in a similar manner as other elements have a "class" property.
So, indeed I will make my property be: "public string #class {get{} set{}}"

Sanitizing a String for a Property Name

Problem
I need to sanitize a collection of Strings from user input to a valid property name.
Context
We have a DataGrid that works with runtime generated classes. These classes are generated based on some parameters. Parameter names are converted into Properties. Some of these parameter names are from user input. We implemented this and it all seemed to work great. Our logic to sanitizing strings was to only allow numbers and letters and convert the rest to an X.
const string regexPattern = #"[^a-zA-Z0-9]";
return ("X" + Regex.Replace(input, regexPattern, "X")); //prefix with X in case the name starts with a number
The property names were always correct and we stored the original string in a dictionary so we could still show a user friendly parameter name.
However, where the trouble starts is when a string only differs in illegal characters like this:
Parameter Name
Parameter_Name
These were both converted into:
ParameterXName
A solution would be to just generate some safe, unrelated names like A, B C. etc. But I would prefer the name to still be recognizable in debug. Unless it's too complicated to implement this behavior of course.
I looked at other questions on StackOverflow, but they all seem to remove illegal characters, which has the same problem.
I feel like I'm reinventing the wheel. Is there some standard solution or trick for this?
I can suggest to change algorithm of generating safe, unrelated and recognizable names.
In c# _ is valid symbol for member names. Replace all invalid symbols (chr) not with X but with "_"+(short)chr+"_".
demo
public class Program
{
public static void Main()
{
string [] props = {"Parameter Name", "Parameter_Name"};
var validNames = props.Select(s=>Sanitize(s)).ToList();
Console.WriteLine(String.Join(Environment.NewLine, validNames));
}
private static string Sanitize(string s)
{
return String.Join("", s.AsEnumerable()
.Select(chr => Char.IsLetter(chr) || Char.IsDigit(chr)
? chr.ToString() // valid symbol
: "_"+(short)chr+"_") // numeric code for invalid symbol
);
}
}
prints
Parameter_32_Name
Parameter_95_Name

C# variable names with special character

I want to include some special characters in a string variable name in C#.
Example:
string foo-bar = String.Empty;
As far as my understand I can't declare a variable as I mentioned in the above example.
Is there any way around to declare a variable name with "-" included?
From MSDN:
You can't just choose any sequence of characters as a variable name. This isn't as worrying as it might sound, however, because you're still left with a very flexible naming
system.
The basic variable naming rules are as follows:
The first character of a variable name must be either a letter, an underscore character (_), or the at symbol (#).
Subsequent characters may be letters, underscore characters, or numbers.
No, this is not possible to do in C#.
If you really, really, really want to so this, you could use a Dictionary<string, string>:
Dictionary<string, string> someVars = new Dictionary<string, string>()
{
{"foo-bar", String.Empty},
{"bar-foo", "bazinga"}
}
Using them would look like this:
string newstring = someVars["foo-bar"] + "Hello World!";
Instead of just using the variable name, you would look up the string in your dictionary. Note that this is very inefficient and just intended as a joke, so please do no really use this ;)
If you are trying to deserialize object, you can use JsonProperty to acieve this.
Example:
public class SubscriptionListJsonData
{
[JsonProperty(PropertyName = "subscriptions")]
public string SubscriptionData { get; set; }
[JsonProperty(PropertyName = "#nextLink")]
public string nextLink { get; set; }
}
Follow this link for partially reading Json.
You can't do that in c# and most of other programming languages .. I also advice you to follow the C# naming conventions as it help you read your code in a way that -at least for me- always felt comfortable .

Does not match sentence that contains specified character

Im trying to match properties in class. Example class:
public static string ComingSoonPage
{
get { return "/blog-coming-soon.aspx"; }
}
public static string EncodeBase64(string dataToEncode)
{
byte[] bytes = System.Text.ASCIIEncoding.UTF8.GetBytes(dataToEncode);
string returnValue = System.Convert.ToBase64String(bytes);
return returnValue;
}
Im using this kind of regex:
(?:public|private|protected)([\s\w]*)\s+(\w+)[^(]
It matches not only properties but also methods which is wrong. So i want remove from matches sentences that contains (. So it select all but not methods (which contains ( ). How can i achieve that.
Try matching the "{" and the "get {" instead
(public|private|protected|internal)[\s\w]*\s+(\w+)\s*\{\s*get\s*\{
UPDATE
Match only the name of the property
(?<=(public|private|protected|internal)[\s\w]*\s+)\w+(?=\s*\{\s*get\s*\{)
uses the general pattern
(?<=prefix)find(?=suffix)
EDIT
A property might have no modifier (public, private etc.) at all and the type might contain extra characters (e.g. for arrays int[,]. Therefore it would probably be better to test only for the syntax elements following the property name (and the name itself). Also a property could consist of only a setter and be abstract: abstract int[,] Matrix { set; }. I suggest retrieving the property names like this:
\w+(?=\s*\{\s*(get|set)\b)
where \b matches a word beginning or (in this case) a word end.
This may be what you are looking for and this works perfectly! I deserve some treat though :)...
Regex r=new Regex(#"(public|private).*?(?=(public|private|$))",RegexOptions.Singleline);
Regex nr=new Regex(#"\(.*?\)\s+\{",RegexOptions.Singleline);
foreach(Match m in r.Matches(yourCodeFile))//extracts all methods and properties
{
if(!nr.IsMatch(m.Value))//shoots down methods
m.Value;//properties only
}
According to this answer, try using:
for Properties: type and name:
(?:public\s|private\s|protected\s|internal\s)\s*(?:readonly|static\s+)?(?<type>\w+)\s+(?<name>\w+)[\s\r\n]*{
for Fields: type and name:
(?:public\s|private\s|protected\s)\s*(?:readonly|static\s+)?(?<type>\w+)\s+(?<name>\w+);
for Methods: methodName and parameterType and parameter:
(?:public\s|private\s|protected\s|internal\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>\w+)\s+(?<parameter>\w+)\s*,?\s*)+\)
for c# code analysis try Irony or The Roslyn Project, see this sample:
C# and VB.NET Code Searcher - Using Roslyn codeproject

Regular expression to match valid namespace name

I thought this question was asked before but I tried Google but didn't find an answer. Maybe I used wrong keywords.
Is it possible to use regular expression to match valid C# namespace name?
Update:
Thanks everyone for your answers and research! This question is much more complex than I expected. As Oscar Mederos and Joey pointed out, a valid namespace cannot contain C# reserved keywords, and can contain a lot more Unicode characters than Latin letters.
But my current project only need to syntactically validate namespaces. So I accepted primfaktor's answer, but I upvoted all answers.
For me, this worked:
^using (#?[a-z_A-Z]\w+(?:\.#?[a-z_A-Z]\w+)*);$
It matches using lines in C# and returns the complete namespace in the first (and only) match group. You may want to remove ^ and $ to allow for indentation and trailing comments.
Example on RegExr.
I know that the question was how to validate a namespace using a regex, but another way to do it is to make the compiler do the work. I am not certain that what I have here catches 100% of all errors, it does work pretty well. I created this ValidationRule for a project on which I am currently working:
using System.CodeDom.Compiler;
using System.Windows.Controls;
using Microsoft.CSharp;
using System.Text.RegularExpressions;
namespace Com.Gmail.Birklid.Ray.CodeGeneratorTemplateDialog
{
public class NamespaceValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
var input = value as string;
if (string.IsNullOrWhiteSpace(value as string))
{
return new ValidationResult(false, "A namespace must be provided.");
}
else if (this.doubleDot.IsMatch(input))
{
return new ValidationResult(false, "'..' is not valid.");
}
var inputs = (value as string).Split('.');
foreach (var item in inputs)
{
if (!this.compiler.IsValidIdentifier(item))
{
return new ValidationResult(false, string.Format(cultureInfo, "'{0}' is invalid.", item));
}
}
return ValidationResult.ValidResult;
}
private readonly CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
private readonly Regex doubleDot = new Regex("\\.\\.");
}
}
If you want to know if a string can be used as a namespace, you should refer to The C# Language Specifications and look at the grammar that validates the namespace.
The namespace should be a sequence of identifiers separated by a .. Example:
identifier
identifier.identifier
identifier.identifier.identifier
...
And what is an identifier?
available_identifier or #any_identifier
An available_identifier is an any_identifier but cannot be a keyword reserved by the language.
any_identifier is the following:
(_|letter)(letter|number)*
Edit:
I must say that this regex can be really really complicated. Take in count that it is necessary to check if no reserved keywords are used, and here is the list of the reserved keywords:
abstract as base bool break byte case
catch char checked class const
continue decimal default delegate do
double else enum event explicit extern
false finally fixed float for foreach
goto if implicit in int interface
internal is lock long namespace new
null object operator out override
params private protected public
readonly ref return sbyte sealed short
sizeof stackalloc static string struct
switch this throw true try typeof uint
ulong unchecked unsafe ushort using
virtual void volatile while
Can't you split the validation, maybe creating a method in C# or any other language to validate it instead of using only one regex?
To be honest, I suggest you any of those two things:
Implement a parser of that grammar (see the reference). You can do it either by hand or using tools like ANTLR
Implement a method that takes the string you want to validate (let's call it str) and write a file like:
namespace str
{
class A {}
}
and try to compile it :) using msbuild or any C# compiler. If it gives an error, then you know that word is not correct :)
How about this...
(?:[A-Z][a-zA-Z0-9\._]+)+[a-z0-9_]

Categories