Overcoming C# limitations

  • Thread starter Thread starter Danny Liberty
  • Start date Start date
Very simple methods are inlined automatically by the JIT compiler.

I had wondered if that might be the case. Still, it might be nice to be able
to explicitly declare a function as "inline" in order to make sure, or to
make it clear in the code.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Chicken Salad Alchemist

I recycle.
I send everything back to the planet it came from.
 
I agree. And if the method can be in-lined, the compiler will do so (based
on some rules).

--
William Stacey [MVP]

| On 18 Jun 2006 15:27:32 -0700, "Danny Liberty" <[email protected]>
| wrote:
|
| >1. Suppose I have a numerous number of functions that I would like to
| >add an optional parameter to. Since C# does not support optional
| >parameters, I would have to duplicate all these functions and override
| >each of them with another parameter. Is this really necessary?? Is it
| >just me or is the result kind of ugly?
|
| There's the params mechanism that works like varargs in C. But yeah,
| optional parameters don't exist. The CLR doesn't support them so
| runtime linking gets iffy with languages that do support them, like
| Visual Basic. The default value is placed in the calling assembly at
| compile time, so it won't change even if the assembly that holds the
| called method is replaced with a newer version. That sucks.
|
| >2. In C++ I could have defined a macro to instantiate an object and
| >then make a method call. For example:
| >#define MY_FUNC(x) MyObj a; a.func(x);
|
| I just want to say how extremely happy I am that the C# team decided
| to use a limited preprocessor that prevents this sort of pointless
| obfuscation. A macro that looks like a function call but actually
| allocates an object? WTF? Why not define a static method since you
| evidently don't use any specific state data?
| --
| http://www.kynosarges.de
 
Mark said:
I don't think I quite follow you there. All I can tell you is that
such certainty doesn't seem to be very important in C# programming.
But when it is, there are language constructs, coding conventions,
and automated tools to support it.

Yes, there are. IMO the facilities in C++ are better.

-cd
 
Carl Daniel said:
Yes, there are. IMO the facilities in C++ are better.

This discussion has certainly made me understand that viewpoint better. And
to agree that, for the specific cases under discussion, you're right -- C++
is better.
 
Chris said:
On 18 Jun 2006 15:27:32 -0700, "Danny Liberty" <[email protected]>
wrote:

I just want to say how extremely happy I am that the C# team decided
to use a limited preprocessor that prevents this sort of pointless
obfuscation. A macro that looks like a function call but actually
allocates an object? WTF? Why not define a static method since you
evidently don't use any specific state data?



Macros we're EXTREMELY useful in C.
In C++ they were often used, but more often abused (myself included on
occasion) by doing exactly the type of thing that Danny is trying.

I do miss them occasionally in C# although mainly for things like
declaring a constant value instead of declaring a constant type.

On the whole though I think we're probably better off without them.
There is a lot of C# code around as it is that is badly written, badly
laid out and almost impossible to follow. Macros would make it 10 times
worse!


Paul
 
Danny Liberty said:
Nothing is hidden here. Every object's destructor is called when it
leaves scope. You might as well have defined a CString and have a
"hidden" destructor as you call it run when the function leaves. It's a
very simple design concept of programing in C++. I'm not debating
wether C# has done a better job, I'm sure it has. I was just asking if
I could somehow mimic some C++ features that in my opinion, make things
a bit easier to do.

Easier for you or the person who takes over your job?

Michael
 
Mark said:
"Carl Daniel [VC++ MVP]"
Yes, there are. IMO the facilities in C++ are better.

This discussion has certainly made me understand that viewpoint
better. And to agree that, for the specific cases under discussion,
you're right -- C++ is better.

btw - don't get me wrong. I love C# and do almost 100% of my programming in
it. But there are things about C++ that I still like better - there's still
room for more cross-polination between these languages to the betterment of
both.

-cd
 
Carl said:
Marcus said:
You don't have to duplicate the methods. Place all the code in the
method call with the most parameters, and have the other methods call
that one, like this.

public int MyFunc(string s,int optional)
{
// Code goes here ...
}

public int MyFunc(string s)
{
MyFunc(s,10); //Assuming default value for optional is 10
}

.... and while this isn't as elegant as optional parameters, in terms of the
amount of source text you have to write, at runtime it's pretty much a wash,
and perhaps actually better. With optional parameters, the compiler has to
instantiate the optional parameters at every call site, while the forwarding
function instantiates the optional parameters only once. [..]

I made a proposal in this newsgroup a few days ago "[Proposal] Named and
Optional Parameters with Default Values", which would solve the problem
very elagant and with no change of the clr.

Although C# does not support this at this time with short syntax (but I
hope it will do so at a later time), it is possible to use the
underlaying implementation as a good solution is some cases where it
might fit.
The basic idea is to use a second class or struct as a parameter object
which already has the default values and you assign only the
parameter-properties you actually need and pass the object into your method:

-------- my posting --------

I got a similar idea a couple of months ago, but now this one will require
no change to the clr, is relatively easy to implement and would be a great
addition to C# 3.0 :)

so here we go..

To make things simpler and better readable I'd make all default parameters
named parameters so that you can decide for yourself which one to pass and
which not, rather than relying on massively overlaoded methods which
hopefully provide the best overload for you, for example the Image.DrawImage
method has 20 overloads.

I propose a syntax like the following:

public void Open(string path, AccessMode mode = AccessMode.Read,
int bufferSize=1024)
{
// ...
}

As you can see, path is a regular parameter which cannot be omitted, whereas
Mode and BufferSize provide default values and can be omitted when calling
the method.
Named parameters can only be declared behind all regular parameters and if
you have params parameters (variable parameterlist) is must be declared at
the end of the parameterlist. Although you can omit the named parameters if
you pass them they should appear in the same order as they were declared for
better readability.

You could call the example method like the following:

Open("text.txt", $mode=AccessMode.Write, $bufferSize=512);
Open("text.txt", $bufferSize=512);
Open("text.txt", $mode=AccessMode.Write);
Open("text.txt");

Note that an $ sign has to appear before all named parameter so that you
have no naming conflicts with other variables in the callers context.

Additionally there can not be more that one method with the same name and
the same regular parameters to avoid ambiguity, so:

Foo(int i, string a="");
Foo(int i, double f=1.0f);

Would not be allowed because the call Foo(100) could not be resolved.

How will it work?
----------------------------

the following method:

public void Open(string path, AccessMode mode = AccessMode.Read, int
bufferSize=1024)
{
// ...
}

would generate the following code:

public struct OpenParams
{
public AccessMode mode;
public int bufferSize;

// because we cannot have parameterless ctors in structs
public static OpenParams DefaultValues
{
get{
OpenParams instance = new OpenParams();
instance.mode = AccessMode.Read;
instance.bufferSize=1024;
return instance;
}
}
}

public void Open(string path, ref OpenParams parms)
{
// ...
}

and the call:

Open("text.txt", $bufferSize=512);

is compiled as:

OpenParams parms = OpenParams.DefaultValues;
parms.bufferSize=512;
Open("text.txt", ref parms);
 
Of course something is hidden. Let's review your original example:
#define MY_FUNC(x) MyObj a; a.func(x);
void Foo()
{
MY_FUNC(3);
.... more code....
}

Here you are creating & destroying a MyObj, and apparently, the timing
of the destruction is important to the functioning of this routine, and
yet MyObj never appears in the code to Foo(). What about the line
"MY_FUNC(3)" would give a person any clue that an object is being
create there?
 
Back
Top