Shamed by this simple question. For some reason, I want to put all asp.net URLs in an enum. But I got an error: identifer expected
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Admin.Code
{
public enum url
{
/_layouts/Admin/test1.aspx,
/_layouts/Admin/test2.aspx,
/_layouts/Admin/test3.aspx
}
class AdminUrlSettings
{
}
}
Thanks.
Here's something I've done many times to turn enumerated values into "friendly strings". You can also use it to create "string-valued" enums. It's in the same vein as Msonic's solution, but the attribute is built into the Framework.
public enum url
{
[Description(#"/_layouts/Admin/test1.aspx")] Test1,
[Description(#"/_layouts/Admin/test2.aspx")] Test2,
[Description(#"/_layouts/Admin/test2.aspx")] Test3
}
...
public static string GetDescription(this Enum enumValue)
{
object[] attr = enumValue.GetType().GetField(enumValue.ToString())
.GetCustomAttributes(typeof (DescriptionAttribute), false);
if (attr.Length > 0)
return ((DescriptionAttribute) attr[0]).Description;
return enumValue.ToString();
}
//usage
Response.Redirect(url.Test1.GetDescription());
These aren't valid enum identifiers. You'll need string enumerations. Here's an example
You will be able to do something like this:
public enum url
{
[StringValue("/_layouts/Admin/test1.aspx")]
Test1,
[StringValue("/_layouts/Admin/test2.aspx")]
Test2,
[StringValue("/_layouts/Admin/test3.aspx")]
Test3
}
Identifiers in C# can't contain / characters. They are limited to underscores, letters and numbers (and possibly a # prefix). To fix this you need to make the enum values valid C# identifiers
enum url {
test1,
test2,
test3
}
Later turning these into an actual valid url can be done with a switch statement over the value
public static string GetRelativeUrl(url u) {
switch (u) {
case url.test1:
return "/_layouts/Admin/test1.aspx";
case url.test2:
return "/_layouts/Admin/test2.aspx";
case url.test3:
return "/_layouts/Admin/test3.aspx";
default:
// Handle bad URL, possibly throw
throw new Exception();
}
}
Enums don't really work like that. Valid identifiers work the same way variable names do (ie. a combination of letters, numbers and underscores not beginning with a number). Why not just use a list:
List<string> urls = new List<string>{"/_layouts/Admin/test1.aspx", "/_layouts/Admin/test2.aspx", "/_layouts/Admin/test3.aspx"}
or use slightly different identifiers:
public enum url
{
layout_Admin_test1,
layout_Admin_test2,
layout_Admin_test3
}
Related
I would like to display names in title case and also convert the hyphenated names — such as O'Reilly — properly.
Right now, when I use the ToUpperCase function, I get "O'reilly", and that is not what I want.
Here's the function I am using:
#functions
{
public static class TextConvert
{
public static string ToTitleCase(string s)
{
s = s.ToLower();
return Regex.Replace(s, #"(^\w)|(\s\w)",b => b.Value.ToUpper());
}
}
}
How can I do that, accounting for cases like O'Reilly?
You can try It.
var titlecase = PrintName("o'riley");
Call this function
Public static string PrintName(string StrValue)//pass here - o'riley
{
if (!string.IsNullOrEmpty(StrValue))
{
return Regex.Replace(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(StrValue.ToLower()),
"['-](?:.)", m => m.Value.ToUpperInvariant());
}
else
{
return "Something meaningful message";
}
}
You can't do this with technical tools alone. There are African names that do not start with a capital letter at all. As you can see in this utility (http://www.johncardinal.com/tmgutil/capitalizenames.htm), the easiest way out is to actually maintain a list of exceptions and match your name against it.
I am a little rusty on my C# and I am trying to figure out a simple script to use in SSIS that will comb through a text file and extract values based on a specific set of patterns and a specific sequence of said patterns.
I need to specify the individual rows of values from this text input to pass to a text file as output. So contract no, bank num, etc are heads and each row is a wrapped value within the file. I just need to be able to comb through and ID rows for output and was thinking that a regular expression could do the trick but I am unsure how to put something like that together. Is it possible to have it ID each row by looking for value patterns in a particular sequence?
I.E.
Pattern1 = [0-9] {9} for contract num
Pattern2 = [a-z][0-9] {6} for bank num
But look for instances where Pattern1 is before Pattern2?
I hope that makes sense.
Any and all help is greatly appreciated.
Thanks.
Sample Text
The file you're working with appears to be fixed width; whoever wrote the program that generates this file, he was communicating the meaning of each field by its position. So it is best that your program consume the information the way it was passed, by interpreting the data based on its position, not its ability to match a particular regular expression. That being said, regular expressions would be a great way to validate the data after it is parsed.
To work with this kind of data, I would probably build a class that represents a single record, and give it methods for parsing and validating. Here is something I came up with pretty quickly:
public class DetailRecord
{
private readonly string _originalText;
static private Dictionary<string, Func<string,string>> _map = new Dictionary<string, Func<string,string>>
{
{ "ContractNo", s => s.Substring( 1 ,10 ) },
{ "BankNum", s => s.Substring( 15 , 8 ) },
{ "ShortName", s => s.Substring( 35 ,10 ).Trim() }
};
public DetailRecord(string originalText)
{
_originalText = originalText;
}
public string this[string key]
{
get
{
return _map[key](_originalText);
}
}
public string BankNum
{
get { return this["BankNum"]; }
}
public string ContractNo
{
get { return this["ContractNo"]; }
}
public string ShortName
{
get { return this["ShortName"]; }
}
public bool IsValid
{
get
{
int dummy;
if (!int.TryParse(this.ContractNo, out dummy)) return false;
if (!Regex.IsMatch(this.BankNum, #"[A-Z]\d\d\s\s\d\d\d")) return false;
return true;
}
}
}
You'll notice this class keeps a static dictionary (the _map) which contains a list of functions for parsing each field.
Also notice there is an IsValid property which uses a regular expression to validate the bank number. The contract number appears to be straight numeric, and it validates that too.
Test program:
public class Program
{
public static void Main()
{
var input = " 0759651386 X08 606 0209784104 BURTON 3334.24";
var line = new DetailRecord(input);
if (line.IsValid)
{
Console.WriteLine("Contract number: '{0}'", line.ContractNo);
Console.WriteLine("Bank number: '{0}'", line.BankNum);
Console.WriteLine("Short name: '{0}'", line.ShortName);
}
}
}
Output:
Contract number: '0759651386'
Bank number: 'X08 606'
Short name: 'BURTON'
See my code on DotNetFiddle
I want to be able to use the contains function the same way the like operator works in sql. So when I call .contains(%This%%%%%%is%%my%string%%) from a list or whatever such as "This is my string " then the function will return true. I've done a lot of searching and it seems like a lot of people would like this function. So how can this be done or how can a custom like function with the same functionality be made?
EDIT
Thank you, for the quick response. I was able to use a regular expressions inside of my own custom Like function. Below is the code for anyone else who wants to use something similar to SQL Like. In this code the user would input the databaze value and then spaces in that value are replaced with .* to ignore anything in-between the values.Just like using the % to replace spaces and values in SQL. I can then use .Like on my string value called testValue that I am searching through to return true or false depending on if the words or whatever are in my string. I also added ToUpper to ignore the case.
//C# Like function
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace sqllinqstuff
{
class Program
{
static void Main(string[] args)
{
string testValue = "Big RED Car";
string databaze = "big red CAR";
string databaze3 = databaze.Replace(" ", ".*");
databaze3 = databaze3.Replace(" ", ".*");
Console.WriteLine(databaze3);
Console.WriteLine(testValue.Like(databaze3));
Console.Read();
}
}
public static class CaseyStringExtension
{
public static bool Like(this string str,string value)
{
if (!string.IsNullOrEmpty(str))
{
Regex r = new Regex(value.ToUpper());
if (r.IsMatch(str.ToUpper()))
return true;
}
return false;
}
}
}
The result of this test will be true.
The way this would be done is with Regex. The syntax is not the same as a SQL LIKE query so there will be a bit of a learning curve. This is a good tutorial site I often reference, it can get you started with the basics.
Translating your original string you asked about, the regex search pattern would be
.*This.*is.*my.*string.*
Once you get good at it you can do searches like this one I helped create for a password complexity checker
(?=^.{8,}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_])(?=^.*[^\s].*$).*$
The above search looks for a string that has at least 8 characters with at least one lower case letter, one upper case letter, one special character, and no white-space characters.
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_]
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();