Overcoming C# limitations

D

Danny Liberty

Hi,

I've recently encountered some design problems due to the language
limitations of C#.
Here are the scenarios:

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?

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);
This would have been useful since I could use this macro in any scope
knowing that the destructor of MyObj (or instance a) will be called at
the end of the scope without explictly calling any function. For
example:
void Foo()
{
MY_FUNC(3);
.... more code....
} <-- destructor of MyObj would be called here

Now back to C#, the preprocessor is very limited so I cannot define
that macro.
If I encapsulate these two lines of code in a method I obviously loose
this advantage, and so I'm left copying and pasting that block of code
wherever it's needed.

I know this may sound stupid, it's just being used to C++, these
problems seem rather odd.
If I'm missing a cleaner way to do this please let me know.

Thanks,

Danny
 
K

Kevin Spencer

Hi Danny,
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?

This subject has been brought up quite a bit, and there seems to be some
ambivalence about it even at Microsoft. However, in the end, they had to
make a decision, and decided against it. I remember reading a blog entry by
one of the .Net developers at Microsoft some time ago, but don't remember
exactly where it is. There is some discussion of it here
(http://weblogs.asp.net/jcogley/archive/2004/10/08/239646.aspx) as well as a
link to a video in which several of the .Net developers talk about it.
Perhaps someone else remembers the blog entry I have forgotten about.
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);
This would have been useful since I could use this macro in any scope
knowing that the destructor of MyObj (or instance a) will be called at
the end of the scope without explictly calling any function. For
example:

There is no provision in the C# specification for either macros or inline
functions. I can certainly understand the problem with macros (although I'm
sure it is not insurmountable), which are not type-safe, but I do wish there
was a provision for inline functions, which are type-safe in C++, and would
not, I believe, pose any problems in the C# spec. So, I'm on your side on
that one. As for the first, well, I can understand the ambivalence, and at
some point we all have to fish or cut bait, so I'm not complaining about it.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Chicken Salad Alchemist

I recycle.
I send everything back to the planet it came from.
 
M

Marcus Andrén

Hi,

I've recently encountered some design problems due to the language
limitations of C#.
Here are the scenarios:

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?

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
}
 
C

Carl Daniel [VC++ MVP]

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. While there's no
guarantee, it's entirely possible that the JIT will inline the forwarding
function, resulting in exactly the same performance at runtime as you'd have
with the C++ solution.

-cd
 
G

Guest

Danny,
In addition to what Kevin and Carl suggested, you also have the option to
create an "optional parameter" object array using the C# params keyword, and
handle checking these and handling same in the method body.

Regarding macro definitions, can't suggest anything there. "It is what it is".

Not having spent too much time in the C++ world (only enough to become
dangerous) I find C# to be remarkably "non restrictive" in terms of what I
can accomplish with it.
Peter
 
M

Mark Wilden

Danny Liberty said:
1. Suppose I have a numerous number of functions that I would like to
add an optional parameter to.

You -might- reevaluate the design to see if this is really the best way to
accomplish what you want. Mind you, I'm not saying it's necessarily bad, but
it might be a design "smell" that could be fixed by (for example)
introducing a new class. Just a possibility.
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 would just do

new MyObj().func(x);
This would have been useful since I could use this macro in any scope
knowing that the destructor of MyObj (or instance a) will be called at
the end of the scope without explictly calling any function.

Since there's no reference to the object, it will be garbage-collected at
the next opportunity. If the class -must- have destructor semantics (because
it's holding a database connection, e.g.), look into implementing
IDisposable. Otherwise, don't worry about destructors in C#. The main reason
we cared about them in C++ is because we had no garbage collection.

Again, however, I would suggest that -possibly- it's a smell to instantiate
a class just to call one method on it, and then dump the object. Of course,
I could only comment intelligently about that after seeing the actual code
in question.

///ark
 
C

Carl Daniel [VC++ MVP]

Mark said:
e.g.), look into implementing IDisposable. Otherwise, don't worry
about destructors in C#. The main reason we cared about them in C++
is because we had no garbage collection.

Actually, that's largely untrue, especially in "modern style" C++. Modern
C++ practice makes extensive use of object lifetime to define program
behavior. The lack of deterministic object lifetime in C# (other than with
a coding convention like using + IDisposable) makes it difficult to adapt
many successful C++ programming techniques to C#.

While I haven't been able to spend much time writing .NET code in C++/CLI,
one of the things I'd hope to capitalize on is the ability to use
deterministic object lifetime to automate manual conventions like
IDisposable while still generating 100% verifiable managed code.

-cd
 
J

james.curran

Danny said:
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);
This would have been useful since I could use this macro in any scope
knowing that the destructor of MyObj (or instance a) will be called at
the end of the scope without explictly calling any function. For
example:
void Foo()
{
MY_FUNC(3);
.... more code....
} <-- destructor of MyObj would be called here

um... You want to hid the call to the ctor, and then have significant
action in the dtor. Forgive me, but I'm really glad I don't have to
maintain your code....
 
M

Michael C

um... You want to hid the call to the ctor, and then have significant
action in the dtor. Forgive me, but I'm really glad I don't have to
maintain your code....

My thoughts exactly, having the creation of the object hidden like this just
obfuscates the code. IMO, a modern oop language is better off without being
able to #define macros. We'd be much better off with an attribute that could
tell the compiler to inline a function (assuming something like that doesn't
already exist).

Michael
 
M

Mark Wilden

Carl Daniel said:
Actually, that's largely untrue, especially in "modern style" C++. Modern
C++ practice makes extensive use of object lifetime to define program
behavior. The lack of deterministic object lifetime in C# (other than
with a coding convention like using + IDisposable) makes it difficult to
adapt many successful C++ programming techniques to C#.

No, the same RAII technique in C++ is directly transferable to IDisposable.
And far from being a coding convention, IDisposable has the language support
of the 'using' statement.

We -had- to care about object destruction - of all dynamic objects - in C++,
because no one else would do it for us. The cases - in C++ or C# - where an
object must be destroyed / disposed deterministically are very much a
minority.
 
C

Carl Daniel [VC++ MVP]

Mark said:
"Carl Daniel [VC++ MVP]"
Actually, that's largely untrue, especially in "modern style" C++. Modern
C++ practice makes extensive use of object lifetime to define
program behavior. The lack of deterministic object lifetime in C#
(other than with a coding convention like using + IDisposable)
makes it difficult to adapt many successful C++ programming
techniques to C#.

No, the same RAII technique in C++ is directly transferable to
IDisposable. And far from being a coding convention, IDisposable has
the language support of the 'using' statement.

No, IDisposable is a coding convention with minimal language support that
puts the burden on the _user_ of the class to use it right, rather than on
the _designer_ of the class. The language support is nothing but thin
syntactic sugar.
We -had- to care about object destruction - of all dynamic objects -
in C++, because no one else would do it for us.

You're unnecessarily mixing two concepts here: object lifetime and memory
lifetime. GC handles memory lifetime well, but creates problems with
non-deterministic object lifetime.
The cases - in C++ or
C# - where an object must be destroyed / disposed deterministically
are very much a minority.

I would disagree with that for modern C++ practice. If you program "in the
style of the STL", use smart pointers, etc, you rarely deal in object
lifetimes directly. I've scarcely written a call to the delete operator in
C++ in the last 5 years. Instead, having well-defined object lifetimes
allows you to delegate all of that to a few simple components.

The questsion is really not about whether an object _must_ be destroyed at a
given time. Rather, it's about the value of knowing with certainly when an
object will be destroyed. Objects like stream classes that have handles
open, etc, are indeed a minority among classes, but neither are they the
primary beneficiaries of having well defined object lifetimes.

-cd
 
A

Andre Kaufmann

Mark said:
"Carl Daniel [VC++ MVP]" <[email protected]>
wrote in message [...]

No, the same RAII technique in C++ is directly transferable to IDisposable.
And far from being a coding convention, IDisposable has the language support
of the 'using' statement.

If you use the object in a function block only.
But if the object is held in several lists and has to be destroyed
(disposed) if it has been removed from the last list holding file
objects, then you cannot implement this in C# easily.
Doesn't mean that I generally favor reference counting over garbage
collection, but sometimes I find it quite useful. Especially when the
objects are used by different threads.
We -had- to care about object destruction - of all dynamic objects - in C++,
because no one else would do it for us. The cases - in C++ or C# - where an
object must be destroyed / disposed deterministically are very much a
minority.

IMHO most of the objects holding unmanaged resources need to be
destroyed deterministically.

E.g. if you have a File object that is stored in multiple lists and used
by different threads. If the last thread removes it from the list and if
the object isn't used anymore the file shall be close immediately, so
that it isn't locked anymore.
I don't know how to accomplish this easily, without reference counting.
In C# I could implement a wrapper object, which has a close function,
which decreases a close counter and calls the Close method of the
embedded File object, if it reaches zero. But I have to use a try /
finally block and call the Close method in the finally block in C# or
instantiate another wrapper object in C#, which allows me to use the
"using" statement.

I don't care about the memory resources, these are handled quite well by
the garbage collection. But if I have to keep track of my unmanaged
resources, I cannot think of a simple solution in C#. :-(

Andre
 
B

Bruce Wood

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);
This would have been useful since I could use this macro in any scope
knowing that the destructor of MyObj (or instance a) will be called at
the end of the scope without explictly calling any function. For
example:
void Foo()
{
MY_FUNC(3);
.... more code....
} <-- destructor of MyObj would be called here

Now back to C#, the preprocessor is very limited so I cannot define
that macro.

Maybe I'm just being thick about this, but what's wrong with writing a
static method in MyObj:

public static void MyFunc(int x)
{
MyObj a;
a.func(x);
}

Then all you have to say is: MyObj.MyFunc(3)

This idiom is used from time to time in the .NET Framework.

The only thing that this _doesn't_ let you do that the C++ idiom lets
you do is this:

MY_FUNC(3);
.... more code that uses "a" ...

which is really disgusting anyway, and IMHO one of the reasons why
using macros like this sucked in C/C++. Responsible use of the macro,
i.e. refraining from using variables declared within the macro outside
of the macro seems to me to be more-or-less equivalent to a static
method in C#.

Of course, there may be subtleties that I'm missing here....
 
M

Michael C

Bruce Wood said:
Maybe I'm just being thick about this, but what's wrong with writing a
static method in MyObj:

public static void MyFunc(int x)
{
MyObj a;
a.func(x);
}

The code in "func" doesn't seem to care about the state that MyObj starts in
or the state that it is left in. So the function is probably stateless and
should probably just be static anyway.

Michael
 
M

Mark Wilden

Carl Daniel said:
No, IDisposable is a coding convention with minimal language support that
puts the burden on the _user_ of the class to use it right, rather than on
the _designer_ of the class. The language support is nothing but thin
syntactic sugar.

Well, OK, but before you said it was just a coding convention. auto_ptr<> is
a coding convention. IDisposable and 'using' is built into the language.
And if the _user_ is smart enough to use FxCop, it's a no-brainer to conform
to. One could say that destructors are just as much "syntactic sugar."
You're unnecessarily mixing two concepts here: object lifetime and memory
lifetime.

In C++, they're identical - that's why I mentioned it WRT C++.
GC handles memory lifetime well, but creates problems with
non-deterministic object lifetime.

What problems do you refer to? The ones that IDisposable solves, or the ones
when you don't implement IDisposable and don't use 'using' and don't use
FxCop?
I would disagree with that for modern C++ practice. If you program "in
the style of the STL", use smart pointers, etc, you rarely deal in object
lifetimes directly. I've scarcely written a call to the delete operator
in C++ in the last 5 years. Instead, having well-defined object lifetimes
allows you to delegate all of that to a few simple components.

I have to admit that my C++ experience ended in 2000, when auto_ptr<> was
still somewhat controversial, so you may have a point. I don't know if smart
pointers are as widely used today in the C++ world as 'using' is in the C#
world.
The questsion is really not about whether an object _must_ be destroyed at
a given time. Rather, it's about the value of knowing with certainly when
an object will be destroyed. Objects like stream classes that have
handles open, etc, are indeed a minority among classes, but neither are
they the primary beneficiaries of having well defined object lifetimes.

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.
 
C

Chris Nahr

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?
 
M

Mark Wilden

Andre Kaufmann said:
If you use the object in a function block only.
But if the object is held in several lists and has to be destroyed
(disposed) if it has been removed from the last list holding file objects,
then you cannot implement this in C# easily.

That's a good point. However, I think it's rare enough that support for it
doesn't need to be included in the language itself. (By "rare," I don't mean
that it's not done, but that it's done far, far less frequently than simpler
scenarios.)
IMHO most of the objects holding unmanaged resources need to be destroyed
deterministically.

Yes, but I was comparing them to the sum of all objects that are destroyed.
I don't care about the memory resources, these are handled quite well by
the garbage collection. But if I have to keep track of my unmanaged
resources, I cannot think of a simple solution in C#. :-(

Reference counting -is- a simple solution. But much less simpler than C++'s
destructors, I admit.
 
C

Chris Nahr

My thoughts exactly, having the creation of the object hidden like this just
obfuscates the code. IMO, a modern oop language is better off without being
able to #define macros. We'd be much better off with an attribute that could
tell the compiler to inline a function (assuming something like that doesn't
already exist).

Very simple methods are inlined automatically by the JIT compiler.
I think the conditions were something like at most one control
statement, throws no exceptions, and some code size limit.
 
D

Danny Liberty

Yes of course, but I wasn't talking about the actual implementation,
just the duplication of the methods itself that seems to dirty the
code.
 
D

Danny Liberty

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top