|
||
|
|
#1 (permalink) |
|
Forum Newbie
|
Can i use switch with more than one argument? I mean something like this:
Code:
switch(a,b)
{
case 1,5:P{some stuff}
case 1,6:P{some stuff}
case 1,7:P{some stuff}
case 2,5:P{some stuff}
case 3,5:P{some stuff}
}
|
|
|
|
|
|
#3 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
You could, theoretically, concatenate your numbers together into a single string, and then case on the stringified permutations.
case "a,b": ... Kind of ugly, possibly slow. There are of course a fair number of other ways to do this, but nothing quite so compact and elegant as the thing you asked if you could do. If you could do it (which you can't), it would be because C# would have a language native form called a "tuple". Languages that do have tuples allow this sort of thing, and more. Another example of something that you can do with tuple supporting languages is this: a, b = myfunction(); Or also: (a, b) += (1, 2); And of course, the case you mentioned: switch( a, b ) { case( 1, 2) : ... But alas, can't do any of these in C#. Would be nice if you could! C// |
|
|
|
|
|
#4 (permalink) |
|
RunUO Forum Moderator
|
Code:
if ( a==1)
{
if (b==5)
stuff
else if (b==6)
stuff
else if (b==7)
stuff
}
else if (b==5)
{
if (a==2)
stuff
else if (a==3)
stuff
}
If someone know of a better way than PLEASE let me know too.
__________________
I always try to help
![]() Sometimes, I don't know how.... ![]() My Web Page Forum Rules ------------------------------------------------------------- Extensive OWLTR System | Token System | World Teleporters ------------------------------------------------------------- |
|
|
|
|
|
#5 (permalink) |
|
Newbie
Join Date: Nov 2004
Posts: 30
|
You might try something like
switch(slct[a,b]) { case "1_5":P{some stuff} case "1_6":P{some stuff} case "1_7":P{some stuff} case "2_5":P{some stuff} case "3_5":P{some stuff} } where you have set up the array slct to have the values required (also include a default if necessary) You can increment or set your indexes and get a testable string from the array. |
|
|
|
|
|
#6 (permalink) | |
|
RunUO Forum Moderator
|
Quote:
Code:
switch (a+","+b)
{
case "1,5": bla bla
case "1,6": bla bla
case "1,7": bla bla
case "2,5": bla bla
case "3,5": bla bla
}
Keep in mind that working with strings (or string array) use a lot of cpu power and is definatly not advised.
__________________
I always try to help
![]() Sometimes, I don't know how.... ![]() My Web Page Forum Rules ------------------------------------------------------------- Extensive OWLTR System | Token System | World Teleporters ------------------------------------------------------------- |
|
|
|
|
|
|
#7 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
I wouldnt want to go over any code you guys have written
![]() Speed is really irrevelant in such a case and you cant really say shorter code is the fastest one. I would write it as clear as possible and in a more logical way. this is clear but it is not logical Code:
if ( a==1)
{
if (b==5)
stuff
else if (b==6)
stuff
else if (b==7)
stuff
}
else if (b==5)
{
if (a==2)
stuff
else if (a==3)
stuff
}
Code:
if (a==1) //bla bla else //.. Code:
if (a==xx && b==zz) else if ..
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#8 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Code:
if (a==xx && b==zz) else if .. C// |
|
|
|
|
|
#9 (permalink) |
|
Forum Newbie
Join Date: Jul 2004
Posts: 59
|
I beleive switches are generally faster than chained if statements, especially if you have loads of them. To my knowledge switches are placed into a lookup table with an offset. After the comparison is done the program counter is set to the piece of code.
P.S. Found a reference http://en.wikipedia.org/wiki/Jump_table |
|
|
|
|
|
#10 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
It may or may not be that switches are sometimes unrolled to loop tables. However, until one knows the performance concerns of a section of code, one should write code principally for other humans, and not the computer. Agreeably, switch is often pretty clear.
C// |
|
|
|
|
|
#11 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
I really doubt using switch with string concat would much faster than regular a few if-else statements. btw it also has to build that look up table.
anyway event it were faster, does it really matter? how faster could it make it in such a simple case?? nanoseconds??
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#12 (permalink) | |
|
RunUO Forum Moderator
|
Quote:
When you do a lot of string operations you really use a lot more cpu than you may think, you should really avoid string operations where possible.
__________________
I always try to help
![]() Sometimes, I don't know how.... ![]() My Web Page Forum Rules ------------------------------------------------------------- Extensive OWLTR System | Token System | World Teleporters ------------------------------------------------------------- |
|
|
|
|
|
|
#13 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Contatenating the strings is relatively expensive.
Checking for ==/!= is one instruction, even for strings, because C# strings are internalized. An internalized string is essentially a pointer to a string in a table, such that, at any given time, two strings that are spelled the same are actually the same object. If they have the same address, they are the same string, and if they don't, they aren't. So C# just compares their (internal) memory addresses. One instruction for that, basically. Very fast. Hacking the strings together prolly isn't a good idea. Some set of ifs is the right way to do this. C// |
|
|
|
|
|
#14 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
Actually, as far as I know strings in .NEt has an exception for that. It overloads == operator and calls Object.Equal() method for comparisons. So it shouldnt compare the references but objects itself.
Anyway what I meant was actually crappy code vs speed. If you are doing a large amount of iterations, you could change it if it gets faster but otherwise it is not worth it since it compeletely loses its readibility..
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#15 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
The default implementation of Equal for strings is a reference comparison. C# internalizes strings for exactly this performance related reason. The following test confirms this, as there is only a minor difference between the two performance tests, where, if string matching were being performed, the two tests would very greatly in times (they do not).
Code:
using System;
using System.Collections;
using System.Collections.Generic;
//------------------------------------------------------------------------------
public class Test
{
private static int[,] m_Integers = new int[,]
{
{ 1, 3 },
{ 3, 3 },
{ 3, 5 },
{ 5, 5 },
{ 5, 7 },
{ 7, 7 },
{ 7, 11 },
{ 11, 11 },
{ 11, 13 },
{ 13, 13 },
};
private static string[,] m_Strings = new string[,]
{
{ "thisisaridculouslylongstring_one", "thisisaridculouslylongstring_three" },
{ "thisisaridculouslylongstring_three", "thisisaridculouslylongstring_three" },
{ "thisisaridculouslylongstring_three", "thisisaridculouslylongstring_five" },
{ "thisisaridculouslylongstring_five", "thisisaridculouslylongstring_five" },
{ "thisisaridculouslylongstring_five", "thisisaridculouslylongstring_seven" },
{ "thisisaridculouslylongstring_seven", "thisisaridculouslylongstring_seven" },
{ "thisisaridculouslylongstring_seven", "thisisaridculouslylongstring_eleven" },
{ "thisisaridculouslylongstring_eleven", "thisisaridculouslylongstring_eleven" },
{ "thisisaridculouslylongstring_eleven", "thisisaridculouslylongstring_thirteen" },
{ "thisisaridculouslylongstring_thirteen", "thisisaridculouslylongstring_thirteen" },
};
//------------------------------------------------------------------------------
public static void Main( string[] args )
{
{
double start = DateTime.Now.Ticks / 10000000.0;
long count = 0;
for( long i=0; i<100000000; i++)
{
int index = (int)( i % 10L );
if( m_Integers[index,0]==m_Integers[index,1] ) count++;
}
double stop = DateTime.Now.Ticks / 10000000.0;
double elapsed = stop - start;
Console.WriteLine("INTEGERS");
Console.WriteLine(" count: "+count);
Console.WriteLine(" elapsed: "+elapsed);
}
{
double start = DateTime.Now.Ticks / 10000000.0;
long count = 0;
for( long i=0; i<100000000; i++)
{
int index = (int)( i % 10L );
if( m_Strings[index,0]==m_Strings[index,1] ) count++;
}
double stop = DateTime.Now.Ticks / 10000000.0;
double elapsed = stop - start;
Console.WriteLine("STRINGS");
Console.WriteLine(" count: "+count);
Console.WriteLine(" elapsed: "+elapsed);
}
}
}
//------------------------------------------------------------------------------
C// Last edited by Courageous; 10-29-2006 at 10:28 AM. |
|
|
|
|
|
#16 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
C, I dont get the point with your code..
I dont have any compiler right now but try these ones: string a="mystr"; string b="mystr"; Console.WriteLine(a==b); //true Console.WriteLine(a.Equals(b)); //true however then try this one: int x=5; Console.WriteLine((Object)x == (Object)x); //false Console.WriteLine(x.Equals(x)); //true and finally try this one: Object x=5; Object y=5; Console.WriteLine(x==y); //false Console.WriteLine(x.Equals(y)); //true So string camparisons with == operator is different than others. (I couldnt test it.Let me know if any results is not same with mine)
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#17 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
C, I dont get the point with your code...
If it were having to compare every letter of the string, it would have to be many times slower, but it's not. The difference between 100,000,000 compares in the two sets of code is only 1 second. It does address compares (under the hood), with some added overhead. QED. C// Last edited by Courageous; 10-29-2006 at 03:53 PM. |
|
|
|
|
|
#18 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
Small difference doesnt mean it uses references to compare.And why should it mean something like that?? integer comparisons dont use reference comparisons..
This is just a guess, I'll look into it but I think for integer comparisons, it box the value and then calls Int32.Equals() method. Thats why the difference is not huge. Another reason could be caching and optimization done by CLR since none of those variables hasnt change. Anyway, if you compare my first and third examples, I think it is very clear..
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#19 (permalink) | |||
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Quote:
See quote below. Quote:
C# internalizes strings and does reference comparison for equality check by default. Why? Because it's the only fast way to do this. It's also memory-compact, which is why any virtual machine worth its salt always uses string internalization. But by all means, don't believe me. Here's a direct quote from MSDN: Quote:
C// Last edited by Courageous; 10-29-2006 at 04:38 PM. |
|||
|
|
|
|
|
#20 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
What you are saying basicly is "str"=="str" returns false..
Normally, Equals method compare the objects by value and == operator compares them by reference I am pretty sure it doesnt use references to compare. As I said before, string class overloads == operator and calls Equals() method. Easiest way would be just checking IL code of String class by a disassembler but I dont have even .net framework right now ![]()
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#21 (permalink) | |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Quote:
C// Last edited by Courageous; 10-29-2006 at 05:34 PM. |
|
|
|
|
|
|
#22 (permalink) | ||
|
Forum Expert
|
Possibly not what actually happens in the production .NET runtime, but according to Rotor, String.op_Equality calls String.Equals(String, String) which then first does a reference comparison, then if the reference compare comes back false, it does a value comparison. According to Reflector (which I assume disassembles the installed .NET dlls) this behavior also exists in the String class which is in the installed dlls.
The MSDN documentation for String.op_Equality also agrees with this Quote:
Then, there's also another remark in the documentation for String.Intern Quote:
Of course, in all of this I would like to point out, partially for myself, that when it comes to anything past the runtime itself (such as the actual code that the JIT produces and any optimizations it does with the actual machine code generated) all bets are off and anything is possible. Last edited by Sep102; 10-30-2006 at 03:10 AM. |
||
|
|
|
|
|
#23 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
I reran the test by filling the table with string.Copy()'s of the strings instead of the constants, and indeed the string rand about twice as long as the integer test (I would have expected it to be even longer, given the length of the strings, so something is funny there).
I then manually interned this non constant string, and the test dropped back to the original performance figures. So you would appear to be correct. Only constant strings are interned in the .net runtime. When they are, they are reference compared. C// Last edited by Courageous; 10-30-2006 at 01:23 PM. |
|
|
|
|
|
#24 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
so, it uses both reference and value comparison. I didnt know .NEt has an option like internalization of strings. it could be useful where lots of string operation needed.
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#25 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Generally speaking, internalization is quite good. The docs seem to be hinting that the internalization tables aren't garbage collected. A shame.
That's an inadequacy of the CLR, I say. Hopefully they fix it. C// |
|
|