Inheritable Static methods


D

d-42

Hi,

Is there any way to make this method inheritable and have it behave
appropriately on inherited classes? Using generics? Extension methods?
Something else?

class baseClass
{
public static string ClassName()
{
return typeof(baseClass).FullName;
}
}

what I want is for:

class someClass : baseClass
{
....
}

and to be able to call someClass.ClassName() and have it return
"someClass"

obviously I can manually reimplement ClassName() in every inherited
subclass, but it strikes me that there should be -some- way of adding
a static method to a class that returns its own type name, without
having to do it manually for every inherited subclass.

-regards,
Dave
 
Ad

Advertisements

A

Arne Vajhøj

d-42 said:
Is there any way to make this method inheritable and have it behave
appropriately on inherited classes? Using generics? Extension methods?
Something else?

class baseClass
{
public static string ClassName()
{
return typeof(baseClass).FullName;
}
}

what I want is for:

class someClass : baseClass
{
...
}

and to be able to call someClass.ClassName() and have it return
"someClass"

obviously I can manually reimplement ClassName() in every inherited
subclass, but it strikes me that there should be -some- way of adding
a static method to a class that returns its own type name, without
having to do it manually for every inherited subclass.

Why is:

someClass.ClassName()

better than:

typeof(someClass).FullName

?

Arne
 
J

Jon Skeet [C# MVP]

d-42 said:
Is there any way to make this method inheritable and have it behave
appropriately on inherited classes? Using generics? Extension methods?
Something else?

No - the "static" part really means "resolved at compile-time". There's
no such thing as a virtual "per type rather than per instance" member
in C# (although such things exist on other systems).
class baseClass
{
public static string ClassName()
{
return typeof(baseClass).FullName;
}
}

what I want is for:

class someClass : baseClass
{
...
}

and to be able to call someClass.ClassName() and have it return
"someClass"

obviously I can manually reimplement ClassName() in every inherited
subclass, but it strikes me that there should be -some- way of adding
a static method to a class that returns its own type name, without
having to do it manually for every inherited subclass.

When you write someClass.ClassName(), the compiler will replace it with
baseClass.ClassName() in the generated IL.
 
D

d-42

Why is:

someClass.ClassName()

better than:

typeof(someClass).FullName

?

encapsulation
elegance

I want this class hierarchy to provide its class name as part of its
static 'API' because a number of its methods take those class names
as inputs.

-cheers,
Dave
 
D

d-42

No - the "static" part really means "resolved at compile-time". There's
no such thing as a virtual "per type rather than per instance" member
in C# (although such things exist on other systems).

I realize i used the word 'virtual' but I'm only describing the sort
of 'behaviour' I'm talking about. In practice, what I'm asking for
does fall within 'static' resolved at compile-time usage.

The usage is that: someClass.FullName() would be written in the code,
their is no compile time ambiguity what someClass is, its the name of
the type 'someClass'.

And as I said, I could easily, but tediously, write:

static public override string FullName()
{
return typeof(CLASS-NAME-GOES-HERE).FullName;
}
or even simply:
static public override string fullName()
{
return "CLASS-NAME-GOES-HERE";
}

And either would actually meet my need. I just wanted to avoid writing
all these essentially identical methods manually for every subclass in
the hierarchy, and for future subclasses.

Given all these functions all follow an identical format, it seemed
reasonable to imagine that a generic method template could generate
the methods for me.
When you write someClass.ClassName(), the compiler will replace it with
baseClass.ClassName() in the generated IL.

Yes, clearly 'virtual' members aren't going to work here, as they need
an runtime instance.... but I was thinking maybe a generic template
construction or an extension method... something sort of like:

static public string <T>.ClassName() { return typeof(T).FullName;}

Then at compile time, upon seeing someClass.ClassName() the compiler
would not find any pre-defined matches, match it to the template and
generate on the fly:

public string someClass.ClassName() { return
typeof(someClass).FullName;}

and use that. Except of course that doesn't appear to be allowed.

regards,
Dave
 
D

d-42

What you're talking about might make sense in other languages. But in C#,
you're never going to call the "inherited" method without explicitly
providing the type itself. Any static method, even one that meets your
hypothetical goal of being virtual, needs to be called via the type name
itself.

You are absolutely right.

In EVERY usage scenario for this the programmer writing the code
definitelly knows the classname. They could even just enter in the
string itself. The reason for providing it as a property is not
because its unknown, but because its an elegant way of converting the
classname to a string, without hardcoding a string.

For example... any situation where the user might use someClass.Name,
they could just as easily use the string "someClass" directly, never
mind having to use a typeof(someClass).Name.

But I don't believe hard coding the strings is good style. You lose
out on intelli-sense and compile time checking. Its also easier to
propagate changes to the class name to dependant code if the class
name isn't hard coded in strings all over the place.

Using typeof(someClass).Name works just fine, benefits from
intellisense, and compile type checking, etc... so it meets those
requirements.

But if its something I need a lot of why wouldn't I want to
encapsulate it into the class itself, so that instead of having the
user of the class reflect its name to a string whenever they need it,
the class provides a method or property that does it.
That's the point of Arne's question. Let's assume you _could_ come up
with a static virtual method that does what you want. You would still
only ever be calling this method by providing the type name itself.

Agreed. Its just about encapsulation and style.
If
you want the "someClass" implementation, then you'd have to write
"someClass.ClassName()" (or IMHO it'd be a property and you'd write
"someClass.ClassName", but whatever).

Agreed. I'd prefer a property to a method.
How is this significantly better than simply writing
"typeof(someClass).FullName"?

That's basically the same as asking:

How is writing myInt.ToString() significantly better than
Convert.ToString(myInt)

Its not that one is 'signficantly better' than the other. The latter
has an external (Convert) class perform the conversion on the int
type, the former encapsulates the conversion into the int type. Two
different ways of doing the same thing. Nothing wrong with either. And
indeed, for all i know myInt.ToString() is implemented as
Convert.ToString(this) behind the scenes.

That's not really the issue.

In this case, because the the class names will be frequently needed it
makes aesthetic sense to have the class provide its own name, rather
than require the programmers to reflect out themselves each time. Just
like it makes sense for Int to be able to convert itself to a string
without the caller manually invoking a helper class each time.

Either will work. It just seems odd that this particular bit of
functionality can't easily be encapsulated.

cheers,
-Dave
 
Ad

Advertisements

J

Jon Skeet [C# MVP]

I realize i used the word 'virtual' but I'm only describing the sort
of 'behaviour' I'm talking about. In practice, what I'm asking for
does fall within 'static' resolved at compile-time usage.

Well, not really. The exact method to call is resolved at compile-
time, and there *is* only one method to be called - so that method is
indeed called. There's no other context available in C#.
The usage is that: someClass.FullName() would be written in the code,
their is no compile time ambiguity what someClass is, its the name of
the type 'someClass'.

Except that there's no method someClass.FullName(), only
baseClass.FullName() - so that is what's called, and that is what's
resolved at compile-time.

I can see what you want, but there's no way of doing it in C#. I don't
know for sure whether there's any way of doing it in IL, but I doubt
it.
And as I said, I could easily, but tediously, write:

static public override string FullName()

Except you couldn't, because you can only override virtual methods.
You could declare it to be "new" instead though.

<snip>

I'd give up on it, basically - there's no way of doing it in the
current version of C#. Redesign so you don't need it, or live with
using typeof.

Jon
 
D

d-42

Except that there's no method someClass.FullName(), only
baseClass.FullName() - so that is what's called, and that is what's
resolved at compile-time.

This is why I thought generics or extension methods or a combination
of the two might hold a solution. Clearly the method would need to be
generated by the compiler from a method template.
I can see what you want, but there's no way of doing it in C#. I don't
know for sure whether there's any way of doing it in IL, but I doubt
it.

I can live with that. What I couldn't live with was not knowing if I
was just missing something. :)

Thanks for your assistance with this.

-cheers,
Dave
 
D

d-42

Frankly, your use case here is a bit bizarre IMHO (and I mean that in a
good way :) ). I mean, usually people come here complaining that they
can't have virtual static methods because they want to implement something
that's actually impossible to implement. But here, you've got a perfectly
good alternative syntax that does _exactly_ the same thing.

I don't see the problem.

Pete

As I replied to Jon Skeet, I can live with using typeof(x).Name. I
would have liked to have made it a simple static property of the class
for aesthetics, but its not really an issue if I can't.

I just wanted to ensure that I truly couldn't do it, and understand
why, because I was surprised to have stumbled into something that
seemed so simple that I couldn't for the life of me figure out how to
do.

Its not often I find myself facing a situation where to get the effect
I want I'd have to write dozens of almost identical functions and not
be able to refactor it.

Thanks for your insights.

-cheers,
Dave
 
J

Jon Skeet [C# MVP]

Extension methods require an instance.

Not quite. They need an expression of the right type, but that
expression can have a null value. As a horrible, horrible example:

using System;
using System.IO;

public static class Extension
{
public static void ShowType<T>(this T foo)
{
Console.WriteLine(typeof(T));
}
}

public class Test
{
static void Main()
{
string x = null;
x.ShowType();

FileStream fs = null;
fs.ShowType();
}
}

I'm not saying this should be d-42's approach, but...

Jon
 
Ad

Advertisements

D

d-42

Extension methods require an instance.

That's something I learned today. :)
As for generics, well...surely you
could write a generic method that accomplished what you want, but I can't
see how the resulting syntax could wind up preferable to the existing
"typeof(someClass).FullName" solution. As with a non-generic method to do
the same, the generic method would have to exist in some class, requiring
you to use the name of that class, the name of the method, _and_ the name
of the type in question.

Ah, but THAT is precisely the issue extension methods resolve.

After all if I define an extension method:

static public class Util { static public void Print(this string s)
{ Console.Writeline(s);}}

You never see Util when I invoke it. You just see: myString.Print();

So if "static" extension methods could be defined, the extra class
name would be hidden.... of course... we can't so its moot. And even
if we could, I don't think there is any way to pass a "class" as a
parameter.

e.g. if you wanted to define a method:

static void PrintName( ??? x)
{
Console.Writeline(typeof(x).Name);
}

What would the ??? be that would allow you to call:

PrintName(string);

I think the closest I could get would be:

static void PrintName(Type x)
{
Console.Writeline(x.Name);
}

And it would have to be called with:

PrintName(typeof(string));

Is there any way of moving the typeof inside the function, so you can
just call:

PrintName(string);

I don't think you can. Make that two things I learned today. :)

-cheers,
Dave
 
Ad

Advertisements


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