Extension error assignment, how to fix? - c#

We suppose that for example i have a string, and i want to escape it, and to be well reading)
need a working extension what will solve this problem
i tried.
var t = "'";
t.Escape();// == "%27" (what i need), but it not assign result to var. t
t = t.Escape();//works, but ugly.
and the extension
public static string Escape(this string string_2)
{
if (string_2.HasValue())
string_2 = Uri.EscapeDataString(string_2);
return string_2;
}
how to fix this extension be working?

t = t.Escape(); is the usual idiom in .NET for changing a string. E.g. t = t.Replace("a", "b"); I'd recommend you use this. This is necessary because strings are immutable.
There are ways around it, but they are uglier IMO. For example, you could use a ref parameter (but not on an extension method):
public static string Escape (ref string string_2) { ... }
Util.Escape(ref t);
Or you could make your own String-like class that's mutable:
public class MutableString { /** include implicit conversions to/from string */ }
public static string Escape (this MutableString string_2) { ... }
MutableString t = "'";
t.Escape();
I'd caution you that if you use anything besides t = t.Escape();, and thus deviate from normal usage, you are likely to confuse anyone that reads the code in the future.

"Mutable string" in C# is spelled StringBuilder.
So you could do something like this:
public static void Escape(this StringBuilder text)
{
var s = text.ToString();
text.Clear();
text.Append(Uri.EscapeDataString(s));
}
But using it wouldn't really be that great:
StringBuilder test = new StringBuilder("'");
test.Escape();
Console.WriteLine(test);
The real answer is to use the "ugly" string reassignment
t = t.Escape();//works, but ugly.
You'll get used to it. :)

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{}}"

Round-trip-safe escaping of strings in C#

I am confused by all the different escaping mechanisms for strings in C#. What I want is an escaping/unescaping method that:
1) Can be used on any string
2) escape+unescape is guaranteed to return the initial string
3) Replaces all punctuation with something else. If that is too much to ask, then at least commas, braces, and #. I am fine with spaces not being escaped.
4) Is unlikely to ever change.
Does it exist?
EDIT: This is for purposes of seriliazing and deserializing app-generated attributes. So my object may or may not have values for Attribute1, Attribute2, Attribute3, etc. Simplifying a bit, the idea is to do something like the below. Goal is to have the encoded collection be brief and more-or-less human-readable.
I am asking what methods would make sense to use for Escape and Unescape.
public abstract class GenericAttribute {
const string key1 = "KEY1"; //It is fine to put some restrictions on the keys, i.e. no punctuation
const string key2 = "KEY2";
public abstract string Encode(); // NO RESTRICTIONS ON WHAT ENCODE MIGHT RETURN
public static GenericAttribute FromKeyValuePair (string key, string value) {
switch (key) {
case key1: return new ConcreteAttribute1(value);
case key2: return new ConcreteAttribute2(value);
// etc.
}
}
}
public class AttributeCollection {
Dictionary <string, GenericAttribute> Content {get;set;}
public string Encode() {
string r = "";
bool first = true;
foreach (KeyValuePair<string, GenericAttribute> pair in this.Content) {
if (first) {
first = false;
} else {
r+=",";
}
r+=(pair.Key + "=" + Escape(pair.Value.Encode()));
}
return r;
}
public AttributeCollection(string encodedCollection) {
// input string is the return value of the Encode method
this.Content = new Dictionary<string, GenericAttribute>();
string[] array = encodedCollection.Split(',');
foreach(string component in array) {
int equalsIndex = component.IndexOf('=');
string key = component.Substring(0, equalsIndex);
string value = component.Substring(equalsIndex+1);
GenericAttribute attribute = GenericAttribute.FromKeyValuePair(key, Unescape(value));
this.Content[key]=attribute;
}
}
}
I'm not entirely sure what your asking, but I believe your intent is for the escaped character to be included, even with the escape.
var content = #"\'Hello";
Console.WriteLine(content);
// Output:
\'Hello
By utilizing the # it will include said escaping, making it apart of your string. That is for the server-side with C#, to account for other languages and escape formats only you would know that.
You can find some great information on C# escaping here:
MSDN Blog
Try using HttpServerUtility.UrlEncode and HttpServerUtility.UrlDecode. I think that will encode and decode all the things you want.
See the MSDN Docs and here is a description of the mapping on Wikipedia.

c# if contains AND/OR

Is there a variant of this?
if (blabla.Contains("I'm a noob") | blabla.Contains("sry") | blabla.Contains("I'm a noob "+"sry"))
{
//stuff
}
like:
if (blabla.Contains("I'm a noob) and/or ("sry")
{
//stuff
}
Help is appreciated!
You can't collapse it quite as far as you asked, but you can do:
if (blabla.Contains("I'm a noob") || blabla.Contains("sry"))
{
//stuff
}
The "and" case is handled here because a string with both would actually pass both of the statements in the "Or".
As far as I'm aware, there are no built-in methods to do this. But with a little LINQ and extension methods, you can create your own methods that will check to see if a string contains any or all tokens:
public static class ExtensionMethods{
public static bool ContainsAny(this string s, params string[] tokens){
return tokens.Any(t => s.Contains(t));
}
public static bool ContainsAll(this string s, params string[] tokens){
return tokens.All(t => s.Contains(t));
}
}
You could use it like this (remember, params arrays take a variable number of parameters, so you're not limited to just two like in my example):
var str = "this is a string";
Console.WriteLine(str.ContainsAny("this", "fake"));
Console.WriteLine(str.ContainsAny("doesn't", "exist"));
Console.WriteLine(str.ContainsAll("this", "is"));
Console.WriteLine(str.ContainsAll("this", "fake"));
Output:
True
False
True
False
Edit:
For the record, LINQ is not necessary. You could just as easily write them this way:
public static class ExtensionMethods{
public static bool ContainsAny(this string s, params string[] tokens){
foreach(string token in tokens)
if(s.Contains(token)) return true;
return false;
}
public static bool ContainsAll(this string s, params string[] tokens){
foreach(string token in tokens)
if(!s.Contains(token)) return false;
return true;
}
}
var arr = new[]{"I'm a noob" ,"sry", "I'm a noob +sry"};
if(arr.Any(x => blabla.Contains(x)))
{
}
You can use a regex:
Regex r = new Regex("I'm a noob|sry|I'm a noob sry");
if(r.IsMatch(blabla)) {
//TODO: do something
}
Regular expressions have other advanced features like: a* matches with the empty string, a, aa, aaa,...
The funny part is that if you "compile" the regex (for instance using new Regex("I'm a noob|sry|I'm a noob sry",RegexOptions.Compiled), C# will turn it automatically into the fastest solution mechanism possible. For instance if blabla is a 100k chars string, you will only run once over the entire string. And for instance redundant parts like I'm a noob sry will be omitted automatically.

string.insert multiple values. Is this possible?

Im still learning in C#, and there is one thing i cant really seem to find the answer to.
If i have a string that looks like this "abcdefg012345", and i want to make it look like "ab-cde-fg-012345"
i tought of something like this:
string S1 = "abcdefg012345";
string S2 = S1.Insert(2, "-");
string S3 = S2.Insert(6, "-");
string S4 = S3.Insert.....
...
..
Now i was looking if it would be possible to get this al into 1 line somehow, without having to make all those strings.
I assume this would be possible somehow ?
Whether or not you can make this a one-liner (you can), it will always cause multiple strings to be created, due to the immutability of the String in .NET
If you want to do this somewhat efficiently, without creating multiple strings, you could use a StringBuilder. An extension method could also be useful to make it easier to use.
public static class StringExtensions
{
public static string MultiInsert(this string str, string insertChar, params int[] positions)
{
StringBuilder sb = new StringBuilder(str.Length + (positions.Length*insertChar.Length));
var posLookup = new HashSet<int>(positions);
for(int i=0;i<str.Length;i++)
{
sb.Append(str[i]);
if(posLookup.Contains(i))
sb.Append(insertChar);
}
return sb.ToString();
}
}
Note that this example initialises StringBuilder to the correct length up-front, therefore avoiding the need to grow the StringBuilder.
Usage: "abcdefg012345".MultiInsert("-",2,5); // yields "abc-def-g012345"
Live example: http://rextester.com/EZPQ89741
string S1 = "abcdefg012345".Insert(2, "-").Insert(6, "-")..... ;
If the positions for the inserted strings are constant you could consider using string.Format() method. For example:
string strTarget = String.Format("abc{0}def{0}g012345","-");
string s = "abcdefg012345";
foreach (var index in [2, 6, ...]
{
s = s.Insert(index, "-");
}
I like this
StringBuilder sb = new StringBuilder("abcdefg012345");
sb.Insert(6, '-').Insert(2, '-').ToString();
String s1 = "abcdefg012345";
String seperator = "-";
s1 = s1.Insert(2, seperator).Insert(6, seperator).Insert(9, seperator);
Chaining them like that keeps your line count down. This works because the Insert method returns the string value of s1 with the parameters supplied, then the Insert function is being called on that returned string and so on.
Also it's worth noting that String is a special immutable class so each time you set a value to it, it is being recreated. Also worth noting that String is a special type that allows you to set it to a new instance with calling the constructor on it, the first line above will be under the hood calling the constructor with the text in the speech marks.
Just for the sake of completion and to show the use of the lesser known Aggregate function, here's another one-liner:
string result = new[] { 2, 5, 8, 15 }.Aggregate("abcdefg012345", (s, i) => s.Insert(i, "-"));
result is ab-cd-ef-g01234-5. I wouldn't recommend this variant, though. It's way too hard to grasp on first sight.
Edit: this solution is not valid, anyway, as the "-" will be inserted at the index of the already modified string, not at the positions wrt to the original string. But then again, most of the answers here suffer from the same problem.
You should use a StringBuilder in this case as Strings objects are immutable and your code would essentially create a completely new string for each one of those operations.
http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx
Some more information available here:
http://www.dotnetperls.com/stringbuilder
Example:
namespace ConsoleApplication10
{
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder("abcdefg012345");
sb.Insert(2, '-');
sb.Insert(6, '-');
Console.WriteLine(sb);
Console.Read();
}
}
}
If you really want it on a single line you could simply do something like this:
StringBuilder sb = new StringBuilder("abcdefg012345").Insert(2, '-').Insert(6, '-');

Sanitize XML Attribute Values

How can i easily sanitize the values I pass into the Value property of an XAttribute.
Here's an extension method to clean away your trouble. /0 is not allowed in XML. I'm not sure if other chars are also disallowed, but I believe not. Probably best to start at ' '.
void Main()
{
Console.WriteLine("123\0394".XmlSanitize());
}
public static class XmlHelpers
{
public static string XmlSanitize(this string badString)
{
return new String(badString.Where(c => c >=' ').ToArray());
}
}
You could try:
string value = "!##$%^&*()123%^&*(!##\(*!&10987"
value = System.Security.SecurityElement.Escape(value);
This will escape characters that are invalid as XML attribute values.

Categories