|
bjoernen wrote:
Nobody uses input structs, because the C# language handles a collection of input parameters elegantly.
Ah, but I disagree. Input structs are very useful too! For example you can have overloaded constructors that accept different parameters and types. You can set defaults, and do validation. An input struct is a very nice middle layer between the caller and the callee.
bjoernen wrote:
Lets say you have 10 different methods that each return a result object, but from different classes, for instance Point, Rectangle, ArrayList, etc (some of the framework structs and classes). Lets say you also want to be able to tell if the operation went ok, for all those methods, so you'll need a second output parameter of type bool. Would you go about creating 10 output structs to solve that? Or would you use "out"-parameters? Neither is both elegant and productive.
In practice, no. But in theory, if I were to really apply my own rules of programming to myself 100% of the time, then yes, I'd create different structs. And I'd make the methods consistent, so that they return a bool, indicating success (although I suppose throwing an exception is the neuveau way now, blech).
IMO, the problem, here, is that for all the cool features of something like Visual Studio, it does very little to help in good implementation. If you had a tool that would automatically create the structs for you, then it would be easy and accepted practice. And then, if you needed to modify the struct, you wouldn't have to fix up 10's or 100's of callers to match the new method signature, or create an abortion of overload methods. Obviously though, there is a line between practical and silly. Unfortunately, there are no good guidelines. The current state of [edit]Computer Science[/edit] is a joke, IMO, but that's another matter. It's just that your question has touched on this subject, which is something I like to get up on my soapbox and rant about.
Marc
Microsoft MVP, Visual C#
MyXaml
MyXaml Blog
|
|
|
|
|
Marc Clifton wrote:
Ah, but I disagree. Input structs are very useful too! For example you can have overloaded constructors that accept different parameters and types. You can set defaults, and do validation. An input struct is a very nice middle layer between the caller and the callee.
I've done projects using both designs (simple parameters vs input structs), and I can't see the advantage of input structs. Input structs are usually very specific; they are used for a specific method. Since all mechanisms you describe can be accomplished with/within methods too (overloaded methods and validation inside methods, etc), I see no use of encapsulating the call parameters, just for sake of encapsulation.
Some people argue that it is easier extend the design by adding a parameter to the struct, than it is to the method signature. Just because of this, I would say it tampers with readability. I'll have to look at both method signature and struct to understand how to call this method.
I would say that a method should accept a struct only if the struct exists on it's own merits. For instance, it makes no sense to send x, y, width and height when Rectangle exists.
Marc Clifton wrote:
If you had a tool that would automatically create the structs for you, then it would be easy and accepted practice. And then, if you needed to modify the struct, you wouldn't have to fix up 10's or 100's of callers to match the new method signature, or create an abortion of overload methods
I agree that such tool would be very valuable. But I cant see why for example adding a property to a struct (which gets a default value so it wont break 100 callers) is less work than adding an overloaded method that takes another parameter to the class. The lack of support for optional method parameters in C# is another issue.
Marc Clifton wrote:
The current state of [edit]Computer Science[/edit] is a joke, IMO, but that's another matter. It's just that your question has touched on this subject, which is something I like to get up on my soapbox and rant about.
I was pleasantly surprised with the whole .NET initiative at first, and I have to say that C# is a good improvement over Java, and a huge over C++. I will definately stick with it. But I would have liked to see a bigger "generation leap". Especially on the algorithms and patterns department. What we got is a consitent win API, fancier tools and a few new ones. We still code apps the same way.
I would like to reduce the detail work by having the development environment support many abstract concepts like Hierarchical State Machines and GOF patterns, and let me describe logic in a declarative way, much like Prolog or Lisp. The programmer should not be dealing with implementation details (unless he wants to), but just enforce architectural rules (patterns) and business rules (declarative clauses).
Regards,
Björn Morén
Stockholm, Sweden
|
|
|
|
|
And structs are allocated on the stack, making them excellent for short-time use. A collection is a reference type and is allocated on the heap. The GC will get around to collecting it when it sees fit (and you should rarely force the GC through GC.Collect because it's a synchronous operation). That's a big waste for passing parameter data that is used within the method call and for nothing else (potentially).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
You could just create a struct class(es) Tuple2(...9) and just return that. eg
Tuple3 t = BiteMe(x,y,z);
Alternatively I use:
void BiteMe(out x, out y, out z)
top secret xacc-ide 0.0.1
|
|
|
|
|
C# has nothing to do with it. A single return value is defined in the Common Language Infrastructure, or CLI. This is what defines the Common Intermediate Language (CIL), the Common Language Runtime (CLR), the Common Language System (CLS), and more. C# complies to that specification making it one of many languages that can interoperate with each other through Intermediate Language, or simply IL. To change one you'd have to change the entire specification, and I don't see that happening.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Since out parameters exist, I can't see why Lua-style multiple return values would be difficult to implement in the C# language. In it's rude form it could translate Lua-style method return syntax to the "out"-syntax.
Calling:
int a;<br />
int b;<br />
int c;<br />
a, b, c = BiteMe(x, y, z);
before compilation translates to ->
int a;<br />
int b;<br />
int c;<br />
BiteMe(x, y, z, out a, out b, out c);
Declaring:
public int a, int b, int c BiteMe(int x, int y, int z)<br />
{<br />
return x, y, z;<br />
}
before compilation translates to ->
public void BiteMe(int x, int y, int z, out int a, out int b, out int c)<br />
{<br />
a = x;<br />
b = y;<br />
c = z;<br />
}
Regards,
Björn Morén
Stockholm, Sweden
|
|
|
|
|
Python allows similar multiple function
returns and assignments.
As the Python developers will tell you,
they are mearly implemented as "syntactic
sugar." There's no need for such to
bleed down to the lower implementation
level in this case either.
I've only been messing with C# for a short
time but since I tend to use a lot of Win32
API calls more than multiple assignment I'd
find useful a tool where I could put the
cursor on one of those all caps DEFINES
and have it paste in a const with the correct
value from one of the Windows.h includes.
Hunting that stuff down and typing in
const declarations is the pits!
What a waste of time!
|
|
|
|
|
I am creating a memory game in C# that flashes a pattern on 4 buttons by changing the background images. Then the user repeats the pattern on the same buttons.
My problem is getting a delay to occur between the flashes. The Sleep delays between the calls of flash() seem to all pile up at the beginning of the loop. The last call of flash() is all i see occuring. I run this loop:
//IN Game class code
for(int i = 0; i < buttonTrack.Count; i++) {
flash((int)buttonTrack[i]);
System.Threading.Thread.Sleep(1000);
}
public void flash(int n){
// convert number to button
switch(n) {
case 1 :
form1.redB();
break;
case 2 :
form1.blueB();
break;
case 3 :
form1.yellowB();
break;
case 4 :
form1.greenB();
break;
}
}
//End Game class code
//In Form1 class code
public void redButton() {
button4.BackgroundImage = redOn;
button5.BackgroundImage = blueOff;
button6.BackgroundImage = yelOff;
button7.BackgroundImage = greenOff;
}
public void blueButton() {
//same idea as above
button5.BackgroundImage = blueOn;
button4.BackgroundImage = redOff;
button6.BackgroundImage = yelOff;
button7.BackgroundImage = greenOff;
//ditto for other color methods
}
//End Form1 class code
|
|
|
|
|
Use the WinForms timer component instead. Pausing the thread will make the GUI non-responsive, which very bad for WinForms apps.
Regards,
Björn Morén
Stockholm, Sweden
|
|
|
|
|
You're not allowing the Paint event to fire. You should call Refresh() on each loop after the switch statement.
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
The Second EuroCPian Event will be in Brussels on the 4th of September
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!
|
|
|
|
|
Calling Application.DoEvents() is probably better than Refresh(), because it processes all the events in the queue, not just the paint ones. BTW, you may also need to call Invalidate for each of the buttons. Not sure though.
Marc
Microsoft MVP, Visual C#
MyXaml
MyXaml Blog
|
|
|
|
|
dotnet provides a way cool StackFrame class that can be used to get Reflection information about the call stack, the methods and their parameters. however i don't see how to get the actual values of these parameters, for example the instance of the class defining a method on the call stack.
is that because interpreting the actual data on the call stack is language dependent, or something like that? suppose i am a method and want to know the instance of the class calling me, can i do that? ((c'mon, no cheating by passing Sender as a parameter!!))
Tia.
________________________________________
Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain.
Then perhaps I'd deserve ya, and be even worthy of ya..
if I only had a brain!
|
|
|
|
|
Why not pass sender as a parameter if your method needs that information?
One obvious detail is that the callee may know nothing about the caller. For example, in a third party component that your program calls. The third party component won't know anything about your objects so what can it do with them? If it is all your own code then I think its time to step back and re-examine the design.
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
The Second EuroCPian Event will be in Brussels on the 4th of September
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!
|
|
|
|
|
TuringTest1 wrote:
suppose i am a method and want to know the instance of the class calling me
OK, here goes. Obviously, the instance is available because, when using the debugger, you can click on the prior calls in the stack. That takes you to the caller code, and then you can inspect variables in that instance.
However, what exactly would you do with the instance yourself? The way the debugger gets it is because the class instance is either stored in a CPU register or is somehow obtainable by inspecting the stack (I can't remember if "this" gets pushed or not). Anyways, it's just an address. The debugger is doing some magic by converting the pointer to a class. In C++, that's easy, but in C#, I'm not sure it's possible.
Marc
Microsoft MVP, Visual C#
MyXaml
MyXaml Blog
|
|
|
|
|
Marc, Colin, thanks. Here is a brazen plug-- anyone reading this thread should read MyXaml-- it's way cool.
Responding to Colin's question, if "sender" is only used in very odd cases i want to put the plumbing underground where it belongs. I admit that this is an asthetic judgement, but it makes sense to me. Your code might detect an unusual condition several levels down and want to know the value of something at the top level-- certainly you could percolate this data or create some sort of global variables etc, but in my asthetic sense it's much more appealing to go and grovel for the data in the rare cases when it's needed rather than forcing everybody to look at your dirty laundry all the time. Imho it's exactly analogous the exception handling, you *could* achieve the same effect by passing all kinds of return flags around, but popping the stack is so much more comprehensible.
Back to the question, as Marc asks, how does the debugger do it? the debugger has no problem displaying all the local variables etc. I *assume* the values or pointers are simply coming from the stack. It's also clear that the debugger sometimes gets confused, so examining the stack isn't a slam dunk. What i don't know for a fact that external information gotten from compiling "Debug" isn't required. Also as Marc points out, what i really want isn't exactly the class instance but rather the contents of the field instance.Foobar-- i'm assuming that c# internally uses some sort of pointer and that if i'm either in the correct namespace or able to use reflection that given the instance pointer or whatever it should be easy to get the value of Foobar.
Anyway why would StackFrame return all the cool type information if it wasn't useful? I have to believe Stackframe is intended for more than just getting the NAMES/ signatures of the methods on the stack.
Again, thanks, and thanks in advance for any more hints.
_______________________________________________
Go see Shrek2. Tell me if it isnt the best movie ever. Then read the credits at the end of the movie and estimate the animation budget.
|
|
|
|
|
run tlbimp on cordebug.tlb in the lib dir of the SDK root. That should give you enough to play with (unfortunately its still in my to look at list, so gimme a shout if it works well).
top secret xacc-ide 0.0.1
|
|
|
|
|
Thanks be to Leppie! (can't claim i understand it quite yet but google cordebug seems to be the place to look).
Again, thanks!
________________________________________
Gosh, it would be awful pleas'n, to reason out the reason, for things I can't explain.
Then perhaps I'd deserve ya, and be even worthy of ya..
if I only had a brain!
|
|
|
|
|
TuringTest1 wrote:
is that because interpreting the actual data on the call stack is language dependent,
No, because all languages targeting the CLR compile to Intermediate Language, or IL. The source language you use to write an assembly has little to do with the compiled code (though some compilers support different features of the CLI and compiler optimizations can change the IL a small amount).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Is there a function which given a pathname will return the size of that file in bytes?
Thanks.
|
|
|
|
|
well, use the fileinfo class.
|
|
|
|
|
Thanks, I was looking at that class but missed "Length" - sometimes I can't see the wood for the trees.
Rugby League: The Greatest Game Of All.
|
|
|
|
|
new FileInfo("myPath").Length
|
|
|
|
|
Hi guys
Here is my problem without further ado :-
Let's say I have a COM method as follows -
HRESULT GetHerName([in] LONG id,
[out,retval] BSTR* namestr);
And I've implemented it as -
STDMETHODIMP MyClassHere::GetHerName(LONG id, BSTR* namestr)
{
wchar_t str[100];
*namestr = SysAllocString(str);
return S_OK;
}
Now C# sees this method as -
string GetHerName(int)
and I can use it from C# as :-
string s1 = obj.GetHerName(22);
string s2 = obj.GetHerName(14);
Now my problem is as follows - I have allocated a new BSTR using SysAllocString in my COM method, but this BSTR gets copied into a new String object by the RCW layer. All that's nice for me - but the original BSTR now leaks.
When I originally designed my COM method, my idea would probably have been that the client should free the BSTR using SysFreeString after using it.
But now I do not have such an option.
Anyone knows if RCW handles this for me in some way? Or will memory keep leaking every time GetHerName is called?
Now with my own blog - void Nish(char* szBlog);
My MVP tips, tricks and essays web site - www.voidnish.com
|
|
|
|
|
Hey, Nish...
When working with COM interop, be sure to check out the System.Runtime.InteropServices.Marshal class. It can be very helpful.
For example, there is a Marshal.FreeBSTR method. All this does is call SysFreeBSTR for you, but saves you from having to P/Invoke it yourself which saves you from requiring an extra code access permission or two (unless you P/Invoke'd other APIs). The trick is that Marshal.FreeBSTR requires an IntPtr - the address to the BSTR . You can get the address like so:
private void FreeBSTR(string bstr)
{
GCHandle handle = GCHandle.Alloc(bstr);
try
{
Marshal.FreeBSTR(handle.AddrOfPinnedObject());
}
finally
{
if (handle.IsAllocated) handle.Free();
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hey Heath,
Thanks for the reply.
So are you saying that, the string object that the RCW layer returns to the C# client will still internally refer the BSTR memory?
I'd have thought that the original BSTR returned from the COM method is ignored once its contents are used to construct a new string object.
Heath, are there any MSDN links or articles that explain how RCW internally works?
Thanks once again for some really interesting info
Nish
Now with my own blog - void Nish(char* szBlog);
My MVP tips, tricks and essays web site - www.voidnish.com
|
|
|
|
|