Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

C# Programming

static class inheritance, generalized


I'm trying to construct a compelling example of the need for a language
feature, with full support for generics, to introduce all static members and
nested classes of another type into the current name search scope.

i.e. a very simple application would be

class ManyComputations
{
    calling System.Math;

    ... z = Sin(3*x) + Log(y); // qualifiers not needed

}

This provides a superset of the "inherit from a static class" concept,
without actually using inheritance or conflicting with "sealed".

All C# experts are invited to join the discussion over in
microsoft.public.dotnet.languages.vc in the thread titled "howto decouple in
.NET?"  Some familiarity with C++/CLI is a definite plus.

Thanks.

Ben Voigt [C++ MVP] <r@nospam.nospam> wrote:

> I'm trying to construct a compelling example of the need for a language
> feature, with full support for generics, to introduce all static members and
> nested classes of another type into the current name search scope.

> i.e. a very simple application would be

> class ManyComputations
> {
>     calling System.Math;

>     ... z = Sin(3*x) + Log(y); // qualifiers not needed
> }

> This provides a superset of the "inherit from a static class" concept,
> without actually using inheritance or conflicting with "sealed".

Because it's not actually inheritance, I'd try to avoid using the term
wherever possible.

> All C# experts are invited to join the discussion over in
> microsoft.public.dotnet.languages.vc in the thread titled "howto decouple in
> .NET?"  Some familiarity with C++/CLI is a definite plus.

I'll see if I've got time to join in.

One reason MS *might* want to do it - Java has it :)
The syntax used is quite nice, too - static import. The equivalent
would be static using:

static using System.Math;

I wouldn't suggest doing it within a class though - I'd put it with the
rest of the using statements.

--
Jon Skeet - <s@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

-----------------------------------------------Reply-----------------------------------------------

"Jon Skeet [C# MVP]" <s@pobox.com> wrote in message
news:MPG.20cfcdadb5f77cc01b6@msnews.microsoft.com...

Oh, it has to be available in a class.  Absolutely positively.  But I've
already explained why in the other group.  That's not to say it wouldn't be
nice if it also worked at namespace scope.

Ben Voigt [C++ MVP] <r@nospam.nospam> wrote:

> > I wouldn't suggest doing it within a class though - I'd put it with the
> > rest of the using statements.

> Oh, it has to be available in a class.  Absolutely positively.  But I've
> already explained why in the other group.  That's not to say it wouldn't be
> nice if it also worked at namespace scope.

It looks like we're talking about *completely* different things. The
example you gave of being able to use the Sin and Log methods without
further qualification are very different from the desires you have in
expressed in the VC group, as far as I understand them (which isn't
terribly far).

For the purposes of making static members from one type available in
another type without qualification, adding the capability to using
statements is fine.

I'm not *entirely* sure what you're asking for in the VC group, but it
seems to extend *way* past that.

I think it would be a much more fruitful discussion here than in the
C++ group - and more on-topic too, if you're suggesting a C# feature
rather than a C++ feature.

--
Jon Skeet - <s@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

-----------------------------------------------Reply-----------------------------------------------

"Jon Skeet [C# MVP]" <s@pobox.com> wrote:

> Ben Voigt [C++ MVP] <r@nospam.nospam> wrote:
> For the purposes of making static members from one type available in
> another type without qualification, adding the capability to using
> statements is fine.

As I pointed out in the C++ thread, C# 3.0 does have this exact feature -
they're called Extension Methods.

http://blogs.msdn.com/abhinaba/archive/2005/09/15/467926.aspx
http://msdn2.microsoft.com/en-us/library/ms364047(vs.80).aspx#cs3spec...

--
Chris Mullins, MCSD.NET, MCPD:Enterprise, Microsoft C# MVP
http://www.coversant.com/blogs/cmullins

-----------------------------------------------Reply-----------------------------------------------

Chris Mullins [MVP] <cmull@yahoo.com> wrote:

> > For the purposes of making static members from one type available in
> > another type without qualification, adding the capability to using
> > statements is fine.

> As I pointed out in the C++ thread, C# 3.0 does have this exact feature -
> they're called Extension Methods.

> http://blogs.msdn.com/abhinaba/archive/2005/09/15/467926.aspx
> http://msdn2.microsoft.com/en-us/library/ms364047(vs.80).aspx#cs3spec...

It's not that *exact* feature. For one thing, it doesn't apply to
existing methods. For another, it makes them appear to be instance
methods. I certainly wouldn't want to call x.Sin() + y.Cos() in my code
- I'd much rather be able to use Cos(x) + Sin(y).

It may well go part of the way though, in many cases.

--
Jon Skeet - <s@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

-----------------------------------------------Reply-----------------------------------------------

"Chris Mullins [MVP]" <cmull@yahoo.com> wrote in message
news:O9xCC86pHHA.1144@TK2MSFTNGP02.phx.gbl...

> "Jon Skeet [C# MVP]" <s@pobox.com> wrote:
>> Ben Voigt [C++ MVP] <r@nospam.nospam> wrote:

>> For the purposes of making static members from one type available in
>> another type without qualification, adding the capability to using
>> statements is fine.

> As I pointed out in the C++ thread, C# 3.0 does have this exact feature -
> they're called Extension Methods.

Your post in the C++ thread got recalled before I could look at it.  I was
looking forward to hearing your input, too.

"Ben Voigt [C++ MVP]" <r@nospam.nospam> wrote

> Your post in the C++ thread got recalled before I could look at it.  I was
> looking forward to hearing your input, too.

My post got recalled? How... unexpected. I wonder how that happened.

I can see it in Google Groups, for what it's worth...

--
Chris Mullins, MCSD.NET, MCPD:Enterprise, Microsoft C# MVP
http://www.coversant.com/blogs/cmullins

-----------------------------------------------Reply-----------------------------------------------

"Jon Skeet [C# MVP]" <s@pobox.com> schrieb
> The equivalent
> would be static using:

> static using System.Math;

Hi Jon,

why the keyword static here, why not simply:

using System.Math;

Christof

-----------------------------------------------Reply-----------------------------------------------

On Jun 6, 8:07 am, "Christof Nordiek" <c@nospam.de> wrote:

> "Jon Skeet [C# MVP]" <s@pobox.com> schrieb> The equivalent
> > would be static using:

> > static using System.Math;

> why the keyword static here, why not simply:

> using System.Math;

I suppose that would be okay in C# (in Java you can individually
import classes, not just packages). However, given that it's not doing
*quite* the same thing as normal using directive, I think I'd prefer
the extra "static" to make it more obvious to the reader. If you're
dealing with some unfamiliar libraries, it may not be immediately
clear whether a particular name is a namespace or a class.

Jon

-----------------------------------------------Reply-----------------------------------------------

Ben Voigt [C++ MVP] wrote:

        I agree with Jon, THIS is the C# newsgroup and C# discussions should
be held here. We already have a truckload of offtopic (i.e. which are
more about .NET than C#) discussions here so more ONtopic discussion
here would be great ;)

        What you're suggesting is IMHO running into problems very quickly.
With 'Sin' and 'Cos' you might not have duplicates in scope, but what
if you have?

        Furthermore, the necessity which makes you want what you're suggesting
is the friction between procedural programming and OO programming: math
methods and calculation methods are typical procedural
methods/routines, which don't really fit into the OO paradigm, unless
you'd add Sin() as a method of an int or double for example.

        As the language and framework (C#, .NET) are OO, the routines have to
be placed inside a class. To refer to the methods you now have to
specify in which class they're in. This can be a bit odd at first,
because you just want to call a routine like we all did in C or Pascal
and in these languages you also didn't have to specify in which file
the routine was in, it was just there as long as you'd #include the
header file.

        However, if you would go the route of 'if I have included / imported a
header/namespace with solely routines and no classes, I should be able
to call them without specifying their location', you effectively
breaking down the OO nature of C# and will introduce what C++ also has:
a way to program C-style code, without classes.

        Personally I think every static method has to be specified with the
class it's in. This is for clarity which method is called (so the
reader of the code can easily understand which method is called, a big
helper in getting bug rates down) and also to avoid duplicate names.

                FB      

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

-----------------------------------------------Reply-----------------------------------------------

"Frans Bouma [C# MVP]" <perseus.usenetNOS@xs4all.nl> schrieb

> What you're suggesting is IMHO running into problems very quickly.
> With 'Sin' and 'Cos' you might not have duplicates in scope, but what
> if you have?

This wouldn't be a new problem to C#. Even now using directives can import
duplicate names, in wich cases you have to use the full quailified name to
make a distinction. Or you can use using alias directives to explicitly give
different names to them.

The rules of resolving simple names would remain the same or could easily
extended.

Christof

-----------------------------------------------Reply-----------------------------------------------

On Jun 6, 9:21 am, "Frans Bouma [C# MVP]"

<perseus.usenetNOS@xs4all.nl> wrote:

<snip>

>         What you're suggesting is IMHO running into problems very quickly.
> With 'Sin' and 'Cos' you might not have duplicates in scope, but what
> if you have?

Then you generate a compile-time error saying that you've got to
disambiguate.

>         Furthermore, the necessity which makes you want what you're
> suggesting is the friction between procedural programming and OO
> programming: math methods and calculation methods are typical
> procedural methods/routines, which don't really fit into the OO paradigm,
> unless you'd add Sin() as a method of an int or double for example.

So what do you suggest to make life nicer for those who are doing a
*lot* of trigonometry etc in code?

When used sparingly, it can really improve things IMO. Yes, it goes
against the OO nature of C#, but not everything is cleanly expressed
in OO terms.

Jon

-----------------------------------------------Reply-----------------------------------------------

"Frans Bouma [C# MVP]" <perseus.usenetNOS@xs4all.nl> schrieb

> Furthermore, the necessity which makes you want what you're suggesting
> is the friction between procedural programming and OO programming: math
> methods and calculation methods are typical procedural
> methods/routines, which don't really fit into the OO paradigm, unless
> you'd add Sin() as a method of an int or double for example.

I'm not sure, what you want to say by this. Do you mean OO-languages
shouldn't have static methods at all?

BTW What you suggest would reduce the use of the method. I would have to
explicitly cast an int to double to call the sinus of it, or there had to be
a special version of Sin() in the int class, wich internally would only cast
int to double and call Sin(double).

Christof

-----------------------------------------------Reply-----------------------------------------------

> However, if you would go the route of 'if I have included / imported a
> header/namespace with solely routines and no classes, I should be able
> to call them without specifying their location', you effectively
> breaking down the OO nature of C# and will introduce what C++ also has:
> a way to program C-style code, without classes.

I call shenanigans on your statement that this is anti-OOP.  Consider:

public interface IDataLayer
{
    DataSet GetProducts();
    ...

}

public partial class BusinessLayer <DataLayer>
    where DataLayer : IDataLayer
{

}

public partial class BusinessLayer <DataLayer>
{
    public class DiscountRules
    {
        ...
    }

}

public partial class BusinessLayer <DataLayer>
{
    public class Reporting
    {
        ...
    }

}

public partial class ShoppingCartUI<DataLayer, LookAndFeel>
    where DataLayer : IDataLayer
    where LookAndFeel : IPageFormatter
{
    static using BusinessLayer<DataLayer>;

    public class NavigationMenu
    {
    delegate void NavButtonHandler(UIManager sender, NavigateEventArgs e);

    event NavButtonHandler NavigateViewCart;
    event NavButtonHandler NavigateAccountManagement;
    event NavButtonHandler NavigateSystemManagement;

    // use DiscountRules and Reporting without further qualification
    }

    public class UIManager
    {
        public DataLayer GetDataLayer() { ... }

        NavigationMenu NavMenu;
    }

}

public class LocalDataLayer : IDataLayer
{
    // GetProducts()
    ...

    void BackupNow();
    void ReplayLogs();
    void Vaccuum();

}

public class LocalAdminUI
{
    static using BusinessLayer<LocalDataLayer>;    // needs reporting logic
    static using ShoppingCartUI<LocalDataLayer>;

    static void ShowAuthenticationScreen(UIManager sender, NavigateEventArgs
e) { ... }

}

public class Configuration
{
    static using BusinessLayer<LocalDataLayer>;
    static using ShoppingCartUI<LocalDataLayer>;

    void main()
    {
        UIManager uim = new UIManager();
        uim.NavMenu.NavigateSystemManagement +=
LocalAdminUI.ShowAuthenticationScreen;
    }

}

Now, although ShoppingCartUI and BusinessLayer don't need to know
implementation details about the data layer,
ShoppingCartUI<>.UIManager.GetDataLayer() passes a strongly-typed
LocalDataLayer which the LocalAdminUI can use to trigger a database backup,
vaccuum, etc.  ShoppingCartUI and BusinessLayer would be just as happy with
a ClusteredDataLayer or WebServicesDataLayer, etc.

Ok, this isn't the best example, because the DataLayer is probably a
singleton with a long lifetime and you could just keep a reference to it in
the LocalAdminUI.  But what about more classes.  Consider the case where an
error event is raised because a database query failed.  The handler for that
may need to go well beyond the public interface of the request in order to
perform error analysis, yet getting an adapter class created and subscribed
to the error event for each and every request created isn't necessarily
feasible.  Ok you say, just do a runtime cast to get the more detailed
interface.  Bad idea.  You've lost compile-time static checking -- in the
error handling path, where runtime errors are likely to go unnoticed for the
longest time.  Change to a different request class, and the error handler
still happily passes the unit tests against the old mock object, but now
causes a disaster at runtime at the worst possible time -- when you already
had an error you desperately need information about.

And for my system, which has nothing to do with products or shopping carts
or RDBMS, there are quite a few detectable concerns which need to be kept
loosely coupled but all work on the same object tree.  A language feature to
import non-instance members into the name search space would be a huge help.

-----------------------------------------------Reply-----------------------------------------------

Christof Nordiek wrote:
> "Frans Bouma [C# MVP]" <perseus.usenetNOS@xs4all.nl> schrieb

> > Furthermore, the necessity which makes you want what you're
> > suggesting is the friction between procedural programming and OO
> > programming: math methods and calculation methods are typical
> > procedural methods/routines, which don't really fit into the OO
> > paradigm, unless you'd add Sin() as a method of an int or double
> > for example.

> I'm not sure, what you want to say by this. Do you mean OO-languages
> shouldn't have static methods at all?

        They can come in handy, but static methods are sort of a hack as well
when it comes to pure OO in a language: they give you a way to specify
procedural code in an OO language without having to instantiate an
object to call a method.

        A typical example is a very simple set of routines, namely Add(int,
int) and Substract(int, int). These routines take 2 numbers and work
their logic on them.

        You could argue that they should be placed in a 'Calculator' class
however, the methods itself don't work on the calculator's data, the
calculator class is actually a container to be able to compile the 2
routines, because Add and Substract are actually just routines which
work on the input and produce a single value as output.

        Now, one could bicker over whether this example is a good one or not,
but that's besides the point. The point I'm trying to make is that
there is a friction between OO and procedural: you can't always express
everything in classes the way you WANT TO: sometimes procedural code is
just more convenient. However, to ALLOW that, you effectively have to
open up the language to allow 'modules' with routines which don't
belong to any class, they're just forming a library of routines you can
call.

        In C#, this 'Module' idea is implemented as a class with static
methods. The suggestion now is to drop the static class and simply
allow a module with routines as that's what the end result will look
like.

        I find the class with static methods not pretty, but it has an
advantage over a bucket with routines forming a library: the class name
gives the reader hints where the method is implemented:
Calculator.Add() might be hurting for the eye when it comes to true OO,
however it's IMHO better than having 'Add()' alone, and the reader then
has to GUESS in which module Add is implemented.

> BTW What you suggest would reduce the use of the method. I would have
> to explicitly cast an int to double to call the sinus of it, or there
> had to be a special version of Sin() in the int class, wich
> internally would only cast int to double and call Sin(double).

        Though, ask yourself this: why do we place in one situation the method
working on a class' data IN the class the data is contained in and in
another situation we want to place the method OUTSIDE the class the
data is contained in? 10.Cos() might look weird, I agree, but
logically, it is something in line with "foo123".Substring(2);

                FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

-----------------------------------------------Reply-----------------------------------------------

Ben Voigt [C++ MVP] wrote:

> > However, if you would go the route of 'if I have included /
> > imported a header/namespace with solely routines and no classes, I
> > should be able to call them without specifying their location', you
> > effectively breaking down the OO nature of C# and will introduce
> > what C++ also has:  a way to program C-style code, without classes.

> I call shenanigans on your statement that this is anti-OOP.  Consider:

        Listen, Ben. If you want a discussion about this, you shouldn't pull
things like this. I've better things to do than join a mud fest in some
random newsgroup. I just gave an honest opinion which is also shared
among a lot of C++ developers: a lot of C++ developers want the C-style
coding constructs out of C++. There are also a lot of C++ developers
who think the opposite. All fine, but don't call my argumentation cheap
tricks, because then I'm definitely done here, OK?

        A set of routines which are solely procedural (i.e. you can copy /
paste them into a C program and it works (minor syntax crap ignored),
isn't what OO is all about so if you WANT THAT in an OO program, the
language has to have a construct for that. C# has static methods for
that. It's not great, IMHO, but it gives the oppertunity to add
procedural routines which don't work on a class' internal members to a
C# program.

[snip]

> Ok, this isn't the best example, because the DataLayer is probably a
> singleton with a long lifetime and you could just keep a reference to
> it in the LocalAdminUI.  But what about more classes.  Consider the
> case where an error event is raised because a database query failed.
> The handler for that may need to go well beyond the public interface
> of the request in order to perform error analysis, yet getting an
> adapter class created and subscribed to the error event for each and
> every request created isn't necessarily feasible.  Ok you say, just
> do a runtime cast to get the more detailed interface.  Bad idea.
> You've lost compile-time static checking -- in the error handling
> path, where runtime errors are likely to go unnoticed for the longest
> time.  Change to a different request class, and the error handler
> still happily passes the unit tests against the old mock object, but
> now causes a disaster at runtime at the worst possible time -- when
> you already had an error you desperately need information about.

        I'm not an expert on your system so I see not a real relevance to the
point you're trying to make.

> And for my system, which has nothing to do with products or shopping
> carts or RDBMS, there are quite a few detectable concerns which need
> to be kept loosely coupled but all work on the same object tree.  A
> language feature to import non-instance members into the name search
> space would be a huge help.

        Though why not specify the class in which the method is defined in
front of the method? Math.Cos() instead of Cos() ?

        I don't see the relevance of leaving out 'Math' here. And no, I've
never had the need for calling a static method somewhere but at the
point I'd like to call the static method I didn't know which one.

                FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

-----------------------------------------------Reply-----------------------------------------------

Jon Skeet [C# MVP] wrote:

> On Jun 6, 9:21 am, "Frans Bouma [C# MVP]"
> <perseus.usenetNOS@xs4all.nl> wrote:

> <snip>

> >         What you're suggesting is IMHO running into problems very
> > quickly.  With 'Sin' and 'Cos' you might not have duplicates in
> > scope, but what if you have?

> Then you generate a compile-time error saying that you've got to
> disambiguate.

        When I'm reading code, all I can HOPE for is that I understand that
'Cos' is in 'Math'. It's about clarity.

> >         Furthermore, the necessity which makes you want what you're
> > suggesting is the friction between procedural programming and OO
> > programming: math methods and calculation methods are typical
> > procedural methods/routines, which don't really fit into the OO
> > paradigm, unless you'd add Sin() as a method of an int or double
> > for example.

> So what do you suggest to make life nicer for those who are doing a
> *lot* of trigonometry etc in code?

        I was making a hypothetical example that it is (to me at least) rather
odd that some methods are in classes they work on, and others are in
separate classes. We all do that, putting procedural methods together
in static classes and make the methods static, simply because the
methods have no real type they work on, they're procedural.

> When used sparingly, it can really improve things IMO. Yes, it goes
> against the OO nature of C#, but not everything is cleanly expressed
> in OO terms.

        I agree OO has limits in expressiveness, especially when you need
procedural expressiveness. However EVERY degration in readability of
code, i.e. any degration of clarity, is IMHO the worse thing that can
happen to a language. that's also why I find things like 'yield' and
also delegates to some extend language constructs which should be used
with care and only there when you can't do something else. they break
down clarity of the code: "Ok, this calls a delegate, where does the
code end up now?" These kind of things should be clear, at least as
clear as possible: when a programmer doesn't understand the code s/he
reads in full without errors, s/he can't write 100% bugfree code.

        Simply importing methods and calling them as if they're methods of the
class they're called in, is decreasing the clarity of the code, IMHO
and also makes it possible to program procedural applications. I know
that at times we all just want to have a main routine with some code
and that's it, but one then should pick another language.

                FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

-----------------------------------------------Reply-----------------------------------------------

On Jun 7, 9:14 am, "Frans Bouma [C# MVP]"

<snip>

> 10.Cos() might look weird, I agree, but
> logically, it is something in line with "foo123".Substring(2);

I was going to reply to your response to me, but this is actually the
best example I've seen. As you said elsewhere, readability is vital.
It's more important (to me) than the logic of the thing. I would far
rather read:

double dist = Sqrt (x*x+y*y);

than either of

double dist = (x*x+y*y).Sqrt();
double dist = Math.Sqrt(x*x+y*y);

and likewise I'd much rather read

double foo = Cos(theta) + Sin(alpha);

than

double foo = theta.Cos() + alpha.Sin();
double foo = Math.Cos(theta) + Math.Sin(alpha);

Do you genuinely believe that either the instance method version or
the static method version including the class name conveys the
intention of the code more simply than my preferred version?

Yes, you may occasionally want to use Intellisense to confirm which
class a method actually belongs to - although I'd say that when used
sparingly, it should always be obvious anyway. That productivity
decrease is easily matched by the improvement of readability in cases
like the above.

Could it be used stupidly? Yes. Can it also vastly improve the
readability of certain cases, particularly maths? Absolutely.

Jon

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc