|
I'm afraid that's not true, since the resulting IL is identical.
Regards,
mav
|
|
|
|
|
The two strings are created in both codes. The only difference is that the references to the strings are declared as variables in one code, while in the other code the compiler will create the references itself to handle the strings.
---
b { font-weight: normal; }
|
|
|
|
|
Like the others say, both are the same. #1 is must easier to debug though, and should allways be used (for clarity too). Make a habit of it. We are proffesionals, not script kiddie/wannabe hackers
NOTE: That saying, I still take the 'short' route sometimes
xacc.ide-0.1.1.4 - now with LSharp integration and scripting :)
|
|
|
|
|
I totally agree with your professionals vs script kiddie comment, but on occasion it is sometimes necessary to make sacrifices for performance.
As suggested by Jamie4C I created the following class library and ran it through ILDasm
public class Class1
{
public static string VerboseProgrammingMethod()
{
System.Guid g = Guid.NewGuid();
string s = g.ToString();
string f = s.Substring(0,4);
return f;
}
public static string OneLineProgrammingMethod()
{
return Guid.NewGuid().ToString().Substring(0, 4);
}
}
}
Now in theory the IL code for these two functions should be exactly the same, interestingly there are differences. I am no IL expert so this might be a red herring, but here is the IL code:
.method public hidebysig static string VerboseProgrammingMethod() cil managed
{
.maxstack 3
.locals init ([0] valuetype [mscorlib]System.Guid g,
[1] string s,
[2] string f,
[3] string CS$00000003$00000000)
IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
IL_0005: stloc.0
IL_0006: ldloca.s g
IL_0008: call instance string [mscorlib]System.Guid::ToString()
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: ldc.i4.0
IL_0010: ldc.i4.4
IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
int32)
IL_0016: stloc.2
IL_0017: ldloc.2
IL_0018: stloc.3
IL_0019: br.s IL_001b
IL_001b: ldloc.3
IL_001c: ret
}
.method public hidebysig static string OneLineProgrammingMethod() cil managed
{
.maxstack 3
.locals init ([0] string CS$00000003$00000000,
[1] valuetype [mscorlib]System.Guid CS$00000002$00000001)
IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
IL_0005: stloc.1
IL_0006: ldloca.s CS$00000002$00000001
IL_0008: call instance string [mscorlib]System.Guid::ToString()
IL_000d: ldc.i4.0
IL_000e: ldc.i4.4
IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
int32)
IL_0014: stloc.0
IL_0015: br.s IL_0017
IL_0017: ldloc.0
IL_0018: ret
}
-- modified at 7:02 Monday 9th January, 2006
|
|
|
|
|
Is this the debug or the release build? There shouldn't be any differences in the release build. The debug build will contain some differences which is why the first version of the code is easier to debug (the compiler doesn't perform so many optimisations in debug builds)
ColinMackay.net
"Man who stand on hill with mouth open will wait long time for roast duck to drop in." -- Confucius
"If a man empties his purse into his head, no man can take it away from him, for an investment in knowledge pays the best interest." -- Joseph E. O'Donnell
|
|
|
|
|
The above IL listings were from a debug build, but there are still differences in a release build:
.method public hidebysig static string VerboseProgrammingMethod() cil managed
{
.maxstack 3
.locals init (valuetype [mscorlib]System.Guid V_0,
string V_1,
string V_2)
IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
IL_0005: stloc.0
IL_0006: ldloca.s V_0
IL_0008: call instance string [mscorlib]System.Guid::ToString()
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: ldc.i4.0
IL_0010: ldc.i4.4
IL_0011: callvirt instance string [mscorlib]System.String::Substring(int32,
int32)
IL_0016: stloc.2
IL_0017: ldloc.2
IL_0018: ret
}
.method public hidebysig static string OneLineProgrammingMethod() cil managed
{
.maxstack 3
.locals init (valuetype [mscorlib]System.Guid V_0)
IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid()
IL_0005: stloc.0
IL_0006: ldloca.s V_0
IL_0008: call instance string [mscorlib]System.Guid::ToString()
IL_000d: ldc.i4.0
IL_000e: ldc.i4.4
IL_000f: callvirt instance string [mscorlib]System.String::Substring(int32,
int32)
IL_0014: ret
}
-- modified at 7:31 Monday 9th January, 2006
|
|
|
|
|
After a lot of pain I managed to get the Windows Debugger hooked up to a process containing these two methods (using the MethodImpl attribute to suppress inlining), and dump the JITted code. Here's the result:
OneLineProgrammingMethod:
sub esp,0x10
xor eax,eax
mov [esp],eax
mov [esp+0x4],eax
mov [esp+0x8],eax
mov [esp+0xc],eax
lea ecx,[esp]
call mscorlib_79990000+0x35d28 (799c5d28)
push 0x0
lea ecx,[esp+0x4]
mov edx,[01c415d0]
call mscorlib_79990000+0x35de0 (799c5de0)
push 0x4
mov ecx,eax
xor edx,edx
cmp [ecx],ecx
call mscorlib_79990000+0x6b20 (79996b20)
add esp,0x10
ret VerboseProgrammingMethod:
sub esp,0x10
xor eax,eax
mov [esp],eax
mov [esp+0x4],eax
mov [esp+0x8],eax
mov [esp+0xc],eax
lea ecx,[esp]
call dword ptr [mscorlib_79990000+0x234a08 (79bc4a08)]
push 0x0
lea ecx,[esp+0x4]
mov edx,[01c415d0]
call dword ptr [mscorlib_79990000+0x234a28 (79bc4a28)]
push 0x4
mov ecx,eax
xor edx,edx
cmp [ecx],ecx
call mscorlib_79990000+0x6b20 (79996b20)
add esp,0x10
ret The only difference is that for some reason the JIT compiler has decided to call through a table for the verbose method - the functions called are exactly the same.
I'm actually surprised - I was expecting the IL to be different since the C# compiler does very little optimisation but I wasn't expecting a difference in the JITted code.
Nevertheless you should normally forget about micro-optimisations like this and concentrate on the areas that will have the biggest impact.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
Mike Dimmick wrote: Nevertheless you should normally forget about micro-optimisations like this and concentrate on the areas that will have the biggest impact.
In this example, I agree it is an "optimisation" that will save nano seconds if that.
That being said, if the methods were dealing with much larger objects it could potentially be something worth considering.
|
|
|
|
|
As the only difference in coding is to keep references to the objects created, it doesn't matter how large the objects are. The size of a reference is always the same.
When optimizing code it's very useful to know what the code really does, in order to find out what code is worth optimizing, and how.
Example:
int a = 42;
string y = a + "," + a;
That looks simple, but can be written much more efficient in this more lengthy way:
int a = 42;
string x = a.ToString();
string y = x + "," + x;
The first code will be executed something like:
int a = 42;
string y = string.Concat(Number.FormatInt32((int)new Object(a), null, NumberFormatInfo.GetInstance(null)), (string)(object)",", Number.FormatInt32((int)new Object(a), null, NumberFormatInfo.GetInstance(null)));
while the second code will be executed as:
int a = 42;
string x = Number.FormatInt32(a, null, NumberFormatInfo.GetInstance(null));
string y = string.Concat(x, ",", x);
---
b { font-weight: normal; }
|
|
|
|
|
The latter seems to be faster, is this correct?
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Probably a half second faster over the span of 1 million calls to it. But, of course, your milage may vary depending on your machine and how you drive it.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
hi,
a very simple question:
when i create an windows application in VS the starting point is usually the form.
i would like my base class as a starting point (having the MAIN method) from which i start the gui. how do i do it?
when i simply do:
MyGUI gui = new MyGUI();
gui.Show();
the gui does not show for long.
regards,
rnv
|
|
|
|
|
Application.Run(new MyGUI()) should be enough
|
|
|
|
|
If MyGUI is a form then try with Application.Run(new MyGUI());
|
|
|
|
|
|
Hi everybody! I'm buliding a little Database where I have to insert Data through a mask made with some TextBox form and TextLable form.
Can I bind a dataset to this kind of forms? How can I make possible to show in the boxes the selected row of the dataset?
Do the Framework implements this functionality?
Thank you!
|
|
|
|
|
Why can't I install and start a service using the following code?
<br />
private void Test()<br />
{<br />
try<br />
{<br />
Process p = Process.Start(@"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\regsvcs", @"/fc C:\My.dll");<br />
p.WaitForExit();<br />
if(p.ExitCode != 0)<br />
{ <br />
Console.WriteLine("My service install(RegSvcs) failed!!!");<br />
Console.WriteLine("ExitCode was: "+p.ExitCode);<br />
return;<br />
}<br />
ServiceController sc = new ServiceController("My",Environment.MachineName);<br />
sc.Start();<br />
Console.WriteLine("My service started!");<br />
}<br />
catch(Exception ex)<br />
{<br />
Console.WriteLine("Install failed - Exception!!!");<br />
Console.WriteLine(ex.ToString());<br />
}<br />
}<br />
RegSvcs works fine and the service places itself in the COM+ services (I can see it via the ServiceComponents app), but when the code reaches sc.Start(), it throws an Exception with the following information:
System.InvalidOperationException.
Service My was not found on computer 'MBU'.
InnerException = System.ComponentModel.Win32Exception
(Danish)Den angivne tjeneste findes ikke som en installeret tjeneste
(Translated)The service does not exists as an installed service
Has it something to do with the service being a DLL and not an EXE and therefore you can't start it with a ServiceController?
I can start it manually, by using the Componentservices app and right click on the "My" service.
That means the service works, but just can't be started by the above shown code.
What is going on?
|
|
|
|
|
As for as I know Services must be installed with a Setup Project to work corectly. I never used services, and I am not sure about this, just try it anyway.
|
|
|
|
|
That is actually what I am trying , but I need a CustomInstall event to fire AfterInstall in order to start the service - but it doesn't.
I'm in the high-fidelity first class traveling set.
And I think I need a Lear jet.
|
|
|
|
|
Bad english - it does fire the afterinstall event.
It is the sc.start() call that doesn't work.
|
|
|
|
|
How Can I Call Operator in The following example
namespace A
{
public static MyClass operator <=(MyClass f1, MyClass f2)
{....}
}
and I want to call it from another class ???
|
|
|
|
|
Not sure what you are asking...
If have operator <= overloaded for MyClass, you can use it for MyClass. as in
MyClass a,b;
if (a <= b) .....
If you want to do something like
YourClass a,b;
if (a <= b) .....
you would have to do it again for YourClass.
Cheers,
Sebastian
--
Contra vim mortem non est medicamen in hortem.
|
|
|
|
|
Is there a way to display different context menus(or with different submenus) for a treee view for different nodes. Foe example if i have too roots and I want to display a different menu for the child nodes of the forst root, other than for the children of the seccond root.
I have tryed with after select or mouse up event but I want also to retrieve the selected node that generated the menu but it does`n works.
|
|
|
|
|
Here's code snippet that shows different context menus for selected tree node.
private void Form1_Load(object sender, System.EventArgs e)
{
// create the root node
TreeNode treeNodeRoot = new TreeNode("Root");
treeNodeRoot.Tag = "root";
// create first child node
TreeNode treeNodeChild1 = new TreeNode("Child1");
treeNodeChild1.Tag = "child";
treeNodeRoot.Nodes.Add( treeNodeChild1 );
// create second child node
TreeNode treeNodeChild2 = new TreeNode("Child2");
treeNodeChild2.Tag = "child";
treeNodeRoot.Nodes.Add( treeNodeChild2 );
treeView1.Nodes.Add( treeNodeRoot );
}
///
/// Create context menu
///
/// <param name="tag" />tag value
/// <returns>
private ContextMenu GetContextMenuByTag(string tag)
{
ContextMenu contextMenu = new ContextMenu();
if( tag.StartsWith("child") )
{
contextMenu.MenuItems.Add("Child menu item");
}
else
{
contextMenu.MenuItems.Add("Root menu item");
}
return contextMenu;
}
private void treeView1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button==MouseButtons.Right)
{
// retrive node or use treeView1.SelectedNode
TreeNode theNode= treeView1.GetNodeAt(e.X, e.Y);
if (theNode!=null)
{
if( theNode.Tag!=null )
{
ContextMenu contextMenu =
GetContextMenuByTag((string)theNode.Tag);
contextMenu.Show( treeView1, new Point(e.X, e.Y) );
}
}
}
}
DevIntelligence.com - My blog for .Net Developers
-- modified at 3:16 Monday 9th January, 2006
|
|
|
|
|
Subscribe to the MouseDown event of the Treeview control. In the event handler, code it like
if (e.Button == MouseButtons.Right)
{
Point point = new Point(e.X, e.Y);
TreeNode node = treeView.GetNodeAt(point);
if (node == null)
return;
treeView.SelectedNode = node;
if (node.Tag is TypeX)
{
XContextMenu.Show(treeView, point);
}
else if (node.Tag is TypeY)
{
YContextMenu.Show(treeView, point);
}
}
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
|