473,842 Members | 1,933 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

"All public methods should be virtual" - yes or no / pros & cons

I'm on a team building some class libraries to be used by many other
projects.

Some members of our team insist that "All public methods should be virtual"
just in case "anything needs to be changed". This is very much against my
instincts. Can anyone offer some solid design guidelines for me?

Thanks in advance....
Nov 15 '05
175 8932
Martin Maat [EBL] <du***@somewher e.nl> wrote:
Yes, I understand, but I expect the GC to not bluntly collect garbage until
there's no more garbage to be found with its own thread set to time
critical. I expect it to take caution that it will not be in the apps way by
doing as much as it possibly can in idle time and by, if it really needs to
interfere, collecting some garbage for a minimum period of time and then
return control.


No, that's not what happens.

Just for a bit of fun, I wrote a little program to give the GC some
exercise. It's not actually terribly hard work for the GC, as there
aren't many traversals to do - just a single big array with some
elements in, which sometimes get overridden leaving garbage around. The
program keeps track of the longest amount of time it's taken to
allocate a new byte array. Here it is:

using System;

public class Test
{
static void Main()
{
TimeSpan maxTime = new TimeSpan();
byte[][] array = new byte[100000][];
Random r = new Random();

for (int i=0; i < 100000000; i++)
{
int index = r.Next(array.Le ngth);
int size = r.Next (1000);
DateTime start = DateTime.Now;
array[index] = new byte[size];
DateTime end = DateTime.Now;
TimeSpan time = end-start;
if (time > maxTime)
{
maxTime = time;
Console.WriteLi ne (time.TotalMill iseconds);
}
}
}
}

It *rapidly* goes over 200ms on my laptop (which is a fairly nippy
box).

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #151
On Sun, 1 Feb 2004 02:53:28 -0600, "Daniel O'Connell [C# MVP]"
<onyxkirx@--NOSPAM--comcast.net> wrote:

<snip>
The point I'm trying to make is you *CANNOT* override a method without
changing behaviour, so your second point is moot, it is simply a more
specific version of the first. Overriding is a behaviour change, be it at
the method level, the class level, or the system level. Even if your method
looks like
public override void MyMethod()
{
base.MyMethod() ;
}

I would still argue that it changes the behaviour of the class, although not
significantl y.


<snip>

How?

Aside from rather mundane things like a few spare clock cycles to
perform the extra method call, if a client/calling method cannot
tell, from the *result* of invoking the overriden method, that the
method was, in fact, overriden, exactly in what way has the
/behaviour/ been changed?

Oz
Nov 15 '05 #152
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote:
[...]
In everything but an idealized world, an override should be automatically
considered a change in behaviour. [...]
I'd go further: There is no reason one
would want to override a virtual function
except if one wants to change behaviour.
(Mhmm. OK, if you want to be nitpicking,
the case of overriding pure virtuals
remains to be discussed.)
[...]


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 15 '05 #153
ozbear <oz*****@yahoo. com> wrote:
On Sun, 1 Feb 2004 02:53:28 -0600, "Daniel O'Connell [C# MVP]"
<onyxkirx@--NOSPAM--comcast.net> wrote:
[...] Even if your method
looks like
public override void MyMethod()
{
base.MyMethod() ;
}

I would still argue that it changes the behaviour of the class, although not
significantly.
<snip>

How?

Aside from rather mundane things like a few spare clock cycles to
perform the extra method call, if a client/calling method cannot
tell, from the *result* of invoking the overriden method, that the
method was, in fact, overriden, exactly in what way has the
/behaviour/ been changed?


Don't you consider performance to be
observable behaviour? I find it rather
easy to imagine a case where the above
change could render a whole app useless
due to the performance loss. And while
I can't imagine it, my experience with
that Murphy guy insists that this can
indeed happen where I'm sure it never
would. And I learned to trust this
Murphy experience over the years more
than my own judgements. :)
Oz


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 15 '05 #154
Bret Pehrson <br**@infowest. com> wrote:
[...]
Please elaborate on why you think this changes class behavior. I'll probably
learn something.
Daniel already tried to explain this.
I expect to read your headers, see and
recognize common patterns, understand
your identifiers, and use this interface
as it is with as little need for looking
it up in the docs as possible. If you
don't provide that, then that's one darn
good reason to look for another provider.


I'm not following. Maybe my statements weren't clear, but my intention is
this: any well-meaning programmer that produces code potentially for anyone
else (either directly or indirectly), should include complete and correct
documentation.


Of course. However, if my IDE tells me that
the function whos name I'm just typing is
virtual, I expect the class it belongs to
to be designed so that this function can be
overridden, because that's what virtual
functions are for. If I would find out
through the documentation, that this isn't
true, I would push really hard that we throw
the damn thing out the window and get a more
sensible designed lib.
It is extremely difficult (at best) to determine expected behavior from
prototypes and definitions alone (meaning, no documentation, *NO* comments).
If *you* can take naked prototypes and definitions and understand the usage,
behavior, and characteristics of the interface, then you are in a definite
minority. Personally, I rely heavily on the documentation.
Let's see... I just now have time to read
(and post in) this ng since I have changed
a header and need to re-build. I am working
at a kind of universal config file reader
that you can register functions with which
will get called when specific strings are
found in a config file. What I just did was
to add this function:

void readConfigFile( std::istream& is);

Would you look up the docs on this?
And what if I tell you that what actually I
inserted into the header is this

/*! \brief This reads a config file and calls the appropriate
** functions with the converted arguments for each
** feature string found
** \param is <==> config file to read
*/
void readConfigFile( std::istream& is);

Would you still want to look it up??

And now suppose, this function would do
everything as described, but pass the
arguments for the functins it is supposed
to call in the wrong order. Would you
still insist that, if the docs tell so,
that would be fine???

No no.
I expect to read your headers, see and
recognize common patterns, understand
your identifiers, and use this interface
as it is with as little need for looking
it up in the docs as possible. [...]
This still holds.
[...]


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 15 '05 #155
Bret Pehrson <br**@infowest. com> wrote:
Ah, "I am ignorant so you can't touch me".
Try re-reading. My original point was that you can't assume anything about
performance, because it is strictly tied to the implementation (and underlying
hardware).


You can assume that non-functions will
most likely have less, and never will
have more overhead than virtual functions.
I have yet to read *anything* in either the C or C++ spec that deals w/
performance. The thread is about the positives and negatives of MI, not
implementation-specific or performance.
> The only reason to make a function virtual is to allow it to be
> overridden. Overriding a function is changing behaviour.
Not true.


And then you provide an example demonstrating just what you are denying.


Nay, my good friend. My example does NOT change the behavior of the
**CLASS**. Perhaps you would care to elaborate as to why you think it does...


Suddenly your class causes a log file
to be written. Or another entry into
the log system. Or the trace might fail
and throw. Or...
Documentation should be the second line of support. Your code is the first.


You code is the first line if you are working *in the code*. Although not
explicitly defined as such, this thread has been primarily limited to the
presumption that only the interface is avaialble (i.e. header files). My
documentation comments are based on that.


I think Martin meant this. Declarations
_are_ code, after all.
[...]
Excluding the 'dreaded diamond' issue of MI, can someone substantively say why
MI should *NOT* be part of a language???
I couldn't. But then I hadn't read anything
against MI in this thread.
[...]


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 15 '05 #156
.. <.> wrote:
[...]
Ofcourse C++ is still used but watch C# take the mainstream applications and
C++ for specific interop and time / memory critical applications. [...]

There is more to this. A lot, actually.

There is billions of lines of C/C++ code
out there that nobody will rewrite in C#
(or whatever the mainstreamers consider
today's mainstream language). This not
only needs to compile, it also needs to
get fixed and extended.
There is billions of line of C/C++ code
that is (also) compiled and used on other
platforms than Windows. C# doesn't help
with these at all. While Windows (and thus
maybe .NET someday) might be the main
platform that you and I use, that doesn't
mean it is all there is.

The shop I work for has a lot of code that
runs on Win9X, NT, 2k, XP, MacOS Classic,
MacOSX, Linux, and BSD, using half a dozen
C++ compiler/std lib compinations. And a
lot of it runs either as plugin for various
applications or as a standalone app. There
is no critical performance contraints on
our apps (other than the usual "the faster,
the less the users have to wait"). Still --
.NET and C# are out of question.

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Nov 15 '05 #157
Not sure why you think the GC has no hard time running this code?
With this allocation scheme, very quickly, millions of objects (all < 1000
bytes) tend to survive into gen2.
The result is that, once the gen2 threshold has been reached, the GC kicks
in for a full collect, resulting in a relocation of several tens of
megabytes, which is extremely expensive especially when the garbage is
located near the start of the GC2 heap.

Willy.
relocating
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
Martin Maat [EBL] <du***@somewher e.nl> wrote:
Yes, I understand, but I expect the GC to not bluntly collect garbage
until
there's no more garbage to be found with its own thread set to time
critical. I expect it to take caution that it will not be in the apps way
by
doing as much as it possibly can in idle time and by, if it really needs
to
interfere, collecting some garbage for a minimum period of time and then
return control.


No, that's not what happens.

Just for a bit of fun, I wrote a little program to give the GC some
exercise. It's not actually terribly hard work for the GC, as there
aren't many traversals to do - just a single big array with some
elements in, which sometimes get overridden leaving garbage around. The
program keeps track of the longest amount of time it's taken to
allocate a new byte array. Here it is:

using System;

public class Test
{
static void Main()
{
TimeSpan maxTime = new TimeSpan();
byte[][] array = new byte[100000][];
Random r = new Random();

for (int i=0; i < 100000000; i++)
{
int index = r.Next(array.Le ngth);
int size = r.Next (1000);
DateTime start = DateTime.Now;
array[index] = new byte[size];
DateTime end = DateTime.Now;
TimeSpan time = end-start;
if (time > maxTime)
{
maxTime = time;
Console.WriteLi ne (time.TotalMill iseconds);
}
}
}
}

It *rapidly* goes over 200ms on my laptop (which is a fairly nippy
box).

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #158
"Martin Maat [EBL]" <du***@somewher e.nl> wrote in message
[snip]
I don't think so. To do a collection in a uniprocessor system the GC has to
suspend *all* threads that are currently running managed code.


Yes, I understand, but I expect the GC to not bluntly collect garbage until
there's no more garbage to be found with its own thread set to time
critical.
I expect it to take caution that it will not be in the apps way by
doing as much as it possibly can in idle time and by,


Even if you detect that the program is not currently consuming many
cycles it might do so just a millisecond later. Once a collection is
started it cannot be interrupted because doing so would leave you with
absolutely no garbage collected. Since you were not able to visit all
objects you cannot possibly tell whether anything truly is garbage or
not.
Therefore, the GC has no other choice but to kick in when it feels it
must and then collect *all* the garbage in the generation.
if it really needs to
interfere, collecting some garbage for a minimum period of time and then
return control. The aggression applied is likely to be proportional to the
need. If I (the application programmer) were to generate garbage
relentlessly, the GC will probably start fighting me for processing time at
some point. While I am being a good boy however, not giving it a reason to
pull my leash, I expect it to be very very gentle with me, only collecting
garbage for very short periods.


To some extent the .NET GC does exactly this, by doing faster lower
order generation collections much more often than slower higher order
ones. However, when it comes to hard realtime systems you have to
design your system so that it can deal with the worst case, i.e. a
full gen 2 collection *any time*. If such a collection can take
seconds as remarked by Justin Rogers, then it is suicide to use .NET
for just about any hard realtime application.

Regards,

Andreas
Nov 15 '05 #159
Willy Denoyette [MVP] <wi************ *@pandora.be> wrote:
Not sure why you think the GC has no hard time running this code?
With this allocation scheme, very quickly, millions of objects (all < 1000
bytes) tend to survive into gen2.
Yup.
The result is that, once the gen2 threshold has been reached, the GC kicks
in for a full collect, resulting in a relocation of several tens of
megabytes, which is extremely expensive especially when the garbage is
located near the start of the GC2 heap.


Yes, it was deliberately designed to get as many objects as possible
into generation 2, but in other ways it's very simple - each object
that it looks at is independent, other than the "overarchin g" array. In
other words, the hierarchy itself is very simple - it's very wide, but
very shallow. That was the easiest way I could figure out of exercising
the garbage collector without too many lines of code. If that hadn't
confused it enough I'd have tried harder, but as my first attempt went
over the 200ms threshold, I thought I'd leave it there :)

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #160

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

164
8069
by: Ken Brady | last post by:
I'm on a team building some class libraries to be used by many other projects. Some members of our team insist that "All public methods should be virtual" just in case "anything needs to be changed". This is very much against my instincts. Can anyone offer some solid design guidelines for me? Thanks in advance....
0
9715
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10942
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10671
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10310
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7855
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7035
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5696
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5884
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4499
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.