C# weird string behaviour? - c#

I have a string variable as below:
string testVar = "abc ";
Then I have a if statement as below:
if(this.testVar[this.testVar.Length-1].Equals(" "))
From the above I'm trying to find if the last character is space, if it is space then do something. But it is always false even if my testVar = "abc "?

testVar[…] returns a char, not a string. That’s why an Equals test with a string always returns false. You can fix this easily by comparing to a char. you also don’t need Equals:
if (testVar[testVar.Length - 1] == ' ')
It is worth nothing that, if you had used == initially instead of Equals, you would have gotten a compile time error explaining the problem. This illustrates nicely why it’s good to use early binding rather than late binding (Equals takes an object and hence doesn’t offer compile-time type checking).

Why do you not just use:
if (testVar.EndsWith (" "))

It is always false because a char is never equal to a string.
This would work:
if (this.testVar[this.testVar.Length-1].Equals(' '))
or this
if (this.testVar[this.testVar.Length-1] == ' ')

check this dude
var result = str.Substring(str.LastIndexOf(' ') + 1);

Related

Why would someone write string someString = "" + Convert.toChar(0) instead of someString = "0"

Why would someone write
string someString = "" + Convert.ToChar(0);
instead of
string someString = "0";
I saw this in some code related to smart cards. Is there a particular reason for this, from a technical standpoint?
Convert.ToChar(0) is not the same as '0'. It is the same as '\0' (the null character or null terminator). Why would one use the Convert instead of '\0'? I see no reason why.
Using "" + before the character converts it to a string instead of an char. I prefer to use .ToString() since that makes clear what actually happens. But converting here is absolutely useless since you can simply construct a string at once. So conclusion, the code can be written the best as:
"\0"
"0" is a string literal consisting of the number zero and an embedded string terminator.
I think "" + convertToChar(0) has a string terminator due to "" and another one due to convertToChar(0). So it's still a zero length string.
Abbreviating the latter as "\0" is more conventional.

Why String.Equals is returning false?

I have the following C# code (from a library I'm using) that tries to find a certificate comparing the thumbprint. Notice that in the following code both mycert.Thumbprint and certificateThumbprint are strings.
var certificateThumbprint = AppSettings.CertificateThumbprint;
var cert =
myStore.Certificates.OfType<X509Certificate2>().FirstOrDefault(
mycert =>
mycert.Thumbprint != null && mycert.Thumbprint.Equals(certificateThumbprint)
);
This fails to find the certificate with the thumbprint because mycert.Thumbprint.Equals(certificateThumbprint) is false even when the strings are equal. mycert.Thumbprint == certificateThumbprint also returns false, while mycert.Thumbprint.CompareTo(certificateThumbprint) returns 0.
I might be missing something obvious, but I can't figure out why the Equals method is failing. Ideas?
CompareTo ignores certain characters:
static void Main(string[] args)
{
var a = "asdas"+(char)847;//add a hidden character
var b = "asdas";
Console.WriteLine(a.Equals(b)); //false
Console.WriteLine(a.CompareTo(b)); //0
Console.WriteLine(a.Length); //6
Console.WriteLine(b.Length); //5
//watch window shows both a and b as "asdas"
}
(Here, the character added to a is U+034F, Combining Grapheme Joiner.)
So CompareTo's result is not a good indicator of a bug in Equals. The most likely reason of your problem is hidden characters. You can check the lengths to be sure.
See this for more info.
You may wish to try using an overload of String.Equals that accepts a parameter of type StringComparison.
For example:
myCert.Thumbprint.Equals(certificateThumbprint, StringComparison.[SomeEnumeration])
Where [SomeEnumeration] is replaced with one of the following enumerated constants:
- CurrentCulture
- CurrentCultureIgnoreCase
- InvariantCulture
- InvariantCultureIgnoreCase
- Ordinal
- OrdinalIgnoreCase
Reference the MSDN Documentation found here.
Sometimes when we insert data in database it stores some spaces like "question ". And when you will try to compare it with "question" it returns false. So my suggestion is: please check the value in database or use Trim() method.
In your case, please try:
mycert.Thumbprint != null && mycert.Thumbprint.trim().equals(certificateThumbprint.trim())
I think it will return true if any record will exist.

Failed to use SUBSTRING in TryParse

I found an error in my code, where the subtring is not work, it says "startIndex cannot be larger than the length of string"
static int MyIntegerParse(string possibleInt)
{
int i;
return int.TryParse(possibleInt.Substring(2), out i) ? i : 0;
}
I used the procedure here:
var parsed = File.ReadLines(filename)
.Select(line => line.Split(' ')
.Select(MyIntegerParse)
.ToArray())
.ToArray();
But I don't understand why it's error because I already used the substring before and it's work, can I ask for a help here? thnaks.
sample string:
10192 20351 30473 40499 50449 60234
10192 20207 30206 40203 50205 60226
10192 20252 30312 40376 50334 60252
Substring will fail when possibleInt contains fewer than two characters, so you should add that test to your code as well. I suspect that you Split call produces an empty string during some circumstances. This empty string is passed into your int-parser which then fails on the Substring call. So, you should probably do two things:
Get rid of empty strings in the splitting
Handle short or empty strings deliberately in your parsing code
Getting rid of empty strings is quite easy:
var parsed = File.ReadLines(filename)
.Select(line => line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(MyIntegerParse)
.ToArray())
.ToArray();
Adding deliberate handling of empty strings can be done like so:
static int MyIntegerParse(string possibleInt)
{
if (string.IsNullOrEmpty(possibleInt) || possibleInt.Length < 2)
{
return 0;
}
int i;
return int.TryParse(possibleInt.Substring(2), out i) ? i : 0;
}
...or if you are a fan of compact and hard-to-read constructs:
static int MyIntegerParse(string possibleInt)
{
int i;
return (!string.IsNullOrEmpty(possibleInt)
&& possibleInt.Length >= 2
&& int.TryParse(possibleInt.Substring(2), out i)) ? i : 0;
}
No, I have chosen to return 0 when I get strings that are too short. In your case it might make more sense to return some other value, throw an exception or use a Debug.Assert statement.
The possibleInt string needs to be at least two characters long. When it isn't then you'll see the error that you've described.
Add this before your return statement and see if that helps you figure out what's going on:
Debug.Assert(!string.IsNullOrEmpty(possibleInt) && possibleInt.Length > 2);
When running in Debug mode this will throw an exception if the two cases above are not met.
You could also use a Code Contract like this:
Contract.Assert(!string.IsNullOrEmpty(possibleInt) && possibleInt.Length > 2);
You are getting this exception because you are trying to get the substring of a string starting at an index that is greater than the length of the string.
someString.Substring(x) will give you the substring of someString starting at position x in the string, and it is zero based. You are getting this exception because in this case 2 is outside the range of the particular strings length.
Stick a try catch around it, or a breakpoint and you will see the string that is causing this exception has a length less than 3.
The line you are attempting to parse is not that long. From the C# Specification on Substring:
The zero-based starting character position of a substring in this instance.
The string you are passing in either has 0 or 1 characters in it. You need to modify your code to handle such a situation.
EDIT: Additionally, you should be removing empty elements from your file using an overload of split:
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntires)

How to check if a String is a valid name for a FrameworkElement in WPF?

In my code I'm assigning a String to the name property of a FrameworkElement. This String is automatically generated from another part of the application and represents methods name in Java source code and therefore I want to check if it contains a valid name.
Currently I'm doing it that way:
private string getValidName(String s)
{
return s.Replace("<", "").Replace(">", "").Replace("#", "").Replace("(", "").Replace(")", "").Replace(",", "").Replace(".", "").Replace("$", "").Replace(" ", "");
}
But the problem is that I don't know which letters I have to replace. For example in this code [ and ] are missing as I found out when I was hit with an Exception.
So my question is. Is there a list of allowed symbols? And if yes how can I implement this in a reasonable way?
IMHO, the most pragmatic way would be to replace everything that is not [a-z][A-Z][0-9] with an underscore and additionally put an underscore in front. With this, you can change any arbitrary string into a valid identifier.
I know that this doesn't exactly answer your question, but I think it is still worth thinking about it.
You can achieve this with the following code:
var result = "_" + Regex.Replace(input, #"[^a-zA-Z0-9]", "_");
To avoid potential duplicates, I would also consider replacing each occurence of an invalid character with something unique, for example, its hexadecimal representation in the UTF-8 encoding:
Regex.Replace( s, #"[^a-zA-Z0-9]",
m => {
var bytes = Encoding.UTF8.GetBytes( m.Value );
var hexs = bytes.Select( b => string.Format( "_{0:x2}", b ) );
return String.Concat( hexs );
} );

Convert C# format to VB

I am sure this is a simple question for you guys but I don't know what this developer is doing.
name = String.Format(MyStringBuilder + "");
If I convert this to VB I get the message "operator + is not defined for types system.text.stringbuilder and string". Same thing if I use &.
It looks as if the person who wrote it is attempting to force an implicit conversion of MyStringBuilder to a string using the + operator in conjuction with the empty string.
To perform this assignment in VB you only need:
name = MyStringBuilder.ToString()
In the strictest sense, MyStringBuilder in the original code could be a null instance, at which point making an explicit call to .ToString() would throw an exception. The code sample provided would execute properly, however. In VB, you may want to say
Dim name As String
If MyStringBuilder Is Nothing Then
name = String.Empty
Else
name = MyStringBuilder.ToString()
End If
That doesn't make sense to me because AFAICT passing only one argument to string.format doesn't do anything.
Adding "" to the stringbuilder just coerces it to a string.
name = MyStringBuilder.ToString(); would be how I'd do this in C#. Converting that statement to VB should be loads easier.
Use MyStringBuilder.ToString(). That will fix the problem.
You're trying to concatenate a StringBuilder object and String together - that wouldn't work :)
name = String.Format(MyStringBuilder.ToString() + "");
This should compile correctly.
In VB.NET you would use a "&" instead of a "+"
This line:
name = String.Format(MyStringBuilder + "");
Is causing an implicit cast of MyStringBuilder to string (using the ToString() method) in order to use the "+" operator. It's the same as:
name = String.Format(MyStringBuilder.ToString() + "");
which is the same as
name = MyStringBuilder.ToString();
which becomes this in VB.NET:
name = MyStringBuilder.ToString()

Categories