|
You're welcome.
I wasn't, now I am, then I won't be anymore.
|
|
|
|
|
Suppose two strings,
String S1, S2;
Which is faster:
if( S1.ToLower() == S2.ToLower() )
Or:
if( String.Compare(S1, S2, true) == 0 )
Under what conditions might the relative speed vary?
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
Blake Miller wrote: Under what conditions might the relative speed vary?
- strings are reference-types, and atomic in memory
- Converting them both before the comparison is slower than comparing them directly (there can be only one!)
- Microsoft "advises" to use uppercase constants. Has something to do with efficiency in comparing.
- Does it matter?
The last point is the most important one; readability is important, as it influences maintainability. If you're doing a lot of string-operations, consider a RegEx for the job.
-edit;
Many string operations, most important the Compare and Equals methods, now provide an overload that accepts a StringComparision enumeration value as a parameter.
When you specify either StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase, the string comparison will be non-linguistic. That is, the features that are specific to the natural language are ignored when making comparison decisions. This means the decisions are based on simple byte comparisons and ignore casing or equivalence tables that are parameterized by culture. As a result, by explicitly setting the parameter to either the StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase, your code often gains speed, increases correctness, and becomes more reliable.
It's one of FxCops' warnings[^]
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
modified 2-Nov-12 16:25pm.
|
|
|
|
|
Thank you for your answers.
Would you have a link to a tech note, language guide or MSDN about this part "Microsoft 'advises' to use uppercase constants."
It does matter. I am looking into this because customers are complaining about CPU load.
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
Modified the post to include the FxCop rule
|
|
|
|
|
Blake Miller wrote: It does matter. I am looking into this because customers are complaining about
CPU load.
I think you are barking up the wrong tree if that's the case. As another poster responded, with 1 *MILLION* string comparisons, the difference in performance is non-existant. Your performance issues are likely elsewhere.
|
|
|
|
|
The first one creates two new strings, converting each character to lower-case, and then compares the results.
The second one performs a case-insensitive comparison of each character, without allocating any new strings.
Instinct would say that the second will always out-perform the first. Here's some code to test that:
int ITERATIONS = 1000000;
string s1 = "Hello World";
string s2 = "hello world";
Debug.Assert(s1.ToLower() == s2.ToLower());
Debug.Assert(string.Compare(s1, s2, true) == 0);
var sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < ITERATIONS; i++)
{
Debug.Assert(s1.ToLower() == s2.ToLower());
}
sw1.Stop();
var sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < ITERATIONS; i++)
{
Debug.Assert(string.Compare(s1, s2, true) == 0);
}
sw2.Stop();
Console.WriteLine("ToLower: {0}", sw1.Elapsed);
Console.WriteLine("Compare: {0}", sw2.Elapsed);
On my computer, the output is:
ToLower: 00:00:00.4507542
Compare: 00:00:00.1856049
The ToLower approach takes more than twice as long as the Compare approach.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Confirms my 'gut feeling' and we all know how much we like to depend upon those
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
|
Awesome! Thanks for the link.
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
In terms of application performance (rather than just statement performance.)
If you have not measured the application using appropriate data then your first step would be to do that.
If you have measured and found that this specific method containing this statement is the problem then finding a different algorithmic approach would have much more impact. The goal of course in that case is not to find a faster way to do the comparison but instead to find a way so no comparison at all is needed.
|
|
|
|
|
|
TheGermoz wrote:
has anyone experience of a working solution?
A few; didn't need one for the last years, but I've implemented Hunspell[^], NetSpell[^] and something called "iSpell", whose link I cannot find.
They worked as advertised.
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
apparently they spell simply a text (I can use word?!), but I need to spell the comment in the code from VS
|
|
|
|
|
In that case, you'd need to get familiar with writing a VS-addin; I'd suggest trying to create a prototype for both "problems" (spellcheck a textbox, do something in VS), and working from there.
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
thanks it is a bit complicate, I was looking for a ready to run solution to do not reinvent the wheel.
|
|
|
|
|
TheGermoz wrote: I was looking for a ready to run solution to do not reinvent the wheel
Unless your wheel is better than the one of the competitor, no-one is going to look anyway. Ready-to-run solutions are known paths that are tried and validated.
"Where there's muck, there's money"
|
|
|
|
|
I have been using it for a while on several different computers, and always worked for me. Maybe you should add a Q & A (this is a tab on your link). Apparently somebody else if having problems: "It does work on VS 2010 Premium edition?? Im asking because i have it installed on VS 2010 Premium and it doesnt work"
|
|
|
|
|
|
I want to have a bunch of byte arrays.
They are commands which will be sent to the external device; generally across some sort of serial port (for now, at least).
I want to put them in their own file.
This is to keep the source files manageable from a human point of view.
Pretty much, 300 lines has shown itself to be a very useful generally defining limit as one of the things that helps source code make sense.
How do I put them in a file of their own which still allows them to be seen and used by the methods in the other files ?
I'm getting errors like, "The name Such_And_So does not exist in the current context".
My search for the answer lead me to a page on MSDN about "Scopes" (Found ^Here^ )
That page has what appears to be 15 rules on the scope of anything.
I tried reading a couple of those rules. In order to understand the first thing about any one of those rules, you have to already be an expert in C# to begin with (in which case, you wouldn't need the rules in front of you in the first place).
I just want to keep my source files orderly.
How do I let the methods in one file see the data packets in another file ?
The arrays will look something like this...
byte[] Command_Number___1 = new byte[] {
0xFF, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01
}
;
byte[] Command_Number___2 = new byte[] {
0x0E, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02
}
;
byte[] Command_Number___3 = new byte[] {
0xFD, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03
0x03
}
;
byte[] Command_Number___4 = new byte[] {
0xFC, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04
0x04, 0x04
}
;
byte[] Command_Number___5 = new byte[] {
0xFB, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05
}
;
byte[] Command_Number_etc = new byte[] {
0xFA, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0x0E, 0x0E
}
;
When I put them in a separate file, how do I make them visible to other methods which are in other files ?
It's quite conceivable (indeed normal everyday practice) that this concept will be extended to multiple functions, methods, classes, [whatever you want to call them] and variable names, constants, and who knows what else.
Perhaps the question is: How do I get the compiler and the Linker to cooperate between files ?
Whatever, whatever, thanks for the help.
|
|
|
|
|
Put them in a static class[^] of their own with static getters, and ensure they are part of the namespace of the main application.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Richard MacCutchan wrote: Put them in a static class of their own with static getters, and ensure they are part of the namespace of the main application.
I'm trying to get an idea of all this.
Tried the following, and the code in other files still can't see the names of these groups of data bytes; no matter if I declare them as public or static...
using System;
namespace The_Same_Namespace_As_The_Other_Files
{
public partial class Form1 : Form
{
public byte[] This_Does_Not_Work = new byte[] { 0x01, 0x02 };
}
static class Class1
{
static Class1();
public byte[] The_Command_Set_01 = new byte[] {
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01
}
;
static byte[] Just_A_Test_Set = new byte[] {
0xFF, 0xFE, 0xFD, 0xFC,
0xFB, 0xFA, 0xF9, 0xF8,
0xF7, 0xF6, 0xF5
}
;
}
}
What do I need to do to let my methods in other files see the group called The_Command_Set_01 which is in this file ?
|
|
|
|
|
Your code is not addressing the values in the class. Try this:
public partial class Form1 : Form
{
MessageBox.Show("Value is: {0}", Class1.Just_A_Test_Set[1]);
}
static class Class1
{
public static byte[] The_Command_Set_01 = {
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01
};
public static byte[] Just_A_Test_Set = {
0xFF, 0xFE, 0xFD, 0xFC,
0xFB, 0xFA, 0xF9, 0xF8,
0xF7, 0xF6, 0xF5
};
}
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Aha, so the word "public" can precede the word "static" on the same line. My education continues. Obfuscation rules the world.
I just tried your idea.
In my external file which holds the command bytes (Protocol_Stuff.cs) I have these two groups...
static class Class1
{
static Class1();
public static byte[] BARN_Command_Hello = new byte[] {
0xFF, 0x00, 0x0B, 0x00,
0x11, 0x22, 0x33, 0x44,
0x55, 0x66, 0x77
}
;
public static byte[] BARN_Test = new byte[] {
0xFF, 0x00, 0x0B, 0x00,
0x11, 0x22, 0x33, 0x44,
0x55, 0x66, 0x77
}
;
}
In the file "Form1.cs" I have this...
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Value is: {0}", Class1.BARN_Test[1]);
}
When I choose "Build/Build", C# gives me this response...
Error 1 The name 'Class1' does not exist in the current context E:\YahYah\SoAndSo\Etc\Form1.cs 277 46 TheProgramName_03
So I say: DUH !
This is the problem that I've been trying to overcome for several days. How do I associate the stuff in one file with the stuff in another file ?
e.g., in old-fashioned low-tech anachronistic assembly language (none dare mention speed or size) I would just put...
Extern: BARN_Test ...in the file that uses it and...
Public BARN_Test ...in the file that actually holds the label. The assembler would make the space for it and the linker would put them together.
How do I do that same sort of procedure in C# with separate files ?
|
|
|
|
|
It works fine for me. Did you put the correct namespace clause in your Class1 file?
One of these days I'm going to think of a really clever signature.
|
|
|
|
|