Typedef in C#?

F

Fabio Cannizzo

When you use generic, especially if nested, names can become very long.

Is there a way around that, similar to typedef in C?

E.g. something like

class Mickey<T> {}

"typedef" Mickey<T> MickeyT;

Thanks,
Fabio
 
B

Bruce Wood

No, although in C# 3.0 there will be a "var" declaration that will
infer the type for the variable from the value of the initializing
expression, for example:

var myMickey = new Mickey<T>();

would make "myMickey" a Mickey<T>, because that's what's being used to
initialize it.

Beyond that, no, unless you do it yourself using inheritance:

public class MickeyT : Mickey<T>
{
}

but then you have to repeat all of the constructors in the "alias"
class.
 
N

Nicholas Paldino [.NET/C# MVP]

Fabio,

There is something like it that you can use.

You can do:

using MickeyT = Mickey<T>;

However, T has to be a valid type, you can't use it in a using statement
like that with a type parameter.

Hope this helps.
 
J

Jon Shemitz

Nicholas Paldino said:
using MickeyT = Mickey<T>;

However, T has to be a valid type, you can't use it in a using statement
like that with a type parameter.

And a 'using' alias is a compile-time construct, not a member of the
class. That is, you can only use a MickeyT in a single file/namespace,
you can't refer to a MickeyT from another file or another assembly.
 
S

Scott C

Bruce said:
No, although in C# 3.0 there will be a "var" declaration that will
infer the type for the variable from the value of the initializing
expression, for example:

var myMickey = new Mickey<T>();

would make "myMickey" a Mickey<T>, because that's what's being used to
initialize it.

Is this really true? This smacks of VisualBasic "Option Strict Off", if
you see what I mean.

Scott
 
N

Nick Hounsome

Scott C said:
Is this really true? This smacks of VisualBasic "Option Strict Off", if
you see what I mean.

No because in this case the compiler knows and uses the type whereas in VB
it uses a lot of runtime dynamic invocation stuff.

Specifically the code generated for the C# with either var or Mickey<T> will
be indistinguishable and both will differ from VB with strict off.
 
J

Jon Skeet [C# MVP]

Scott said:
Is this really true? This smacks of VisualBasic "Option Strict Off", if
you see what I mean.

No, it's not like that - the compiler will know the exact type, and
ensure compile-time type safety. It's not really designed particularly
for that usage, however - it's designed for anonymous types, another
feature of C# 3.0. For instance:

var fred = new {Name="Fred", Age=31};

On its own, that doesn't look terribly pleasant either - but combine it
with LINQ and it's a much more compelling story...

I strongly recommend that you have a look at the LINQ and C# 3.0 docs -
they make for fascinating reading.

http://msdn.microsoft.com/netframework/future/linq/

Of course, everything can still change...

Jon
 
N

Nick Hounsome

Jon Skeet said:
No, it's not like that - the compiler will know the exact type, and
ensure compile-time type safety. It's not really designed particularly
for that usage, however - it's designed for anonymous types, another
feature of C# 3.0. For instance:

Strictly it will know the exact compile time type - If the code were:
var MyMickey = (object)new Mickey<T>();
then its type would be Object and you could only call Object methods on it
(unlike VB)

The other nice thing about var is that it makes your code less volatikle in
the face of some type changes such as array to List conversions:

class X
{
int[] GetIt() {...}
}

becomes

class X
{
List<int> GetIt() {...}
}


If code is as follows it does not need to change:

X x;
var a = x.GetIt();
a[3] = 42;

I find this quite common - the class really only wants to contract to return
an 'array like thing' but has to commit to a particular type - interfaces
are a possibility but are less efficient and can be restrictive.

This also allows programming using the C++ template philosophy as seen with
iterators - "If it has the methods of an iterator it can be used as an
iterator". This is already available in slightly different form in the
foreach and using statements.
 
M

Marc Gravell

Actually, I find this particular (cited) usage one of the riskiest, as
changing the return type (and not having to check the referring code) could
be very bad news, and very hard to debug - particulary if it compiles but
suddenly works differently.

I'm not sure that interfaces are less efficient? How about IList<int> in
this case; I *think* (not sure) that int[] implements this (at least, it
compiles), and this then explicitely states what I need to work - i.e. a
Count and an indexer (plus some other things that I don't need).

I think var would be acceptable a: for anonymous decs, b: where the line
declaring the var also defines the type; but usage with a return type that
might be changing in independent code (e.g. separate class / assembly during
indevelopment) makes me fearful... Maybe its too early to predict how well
this will work...

Marc
 
N

Nick Hounsome

Marc Gravell said:
Actually, I find this particular (cited) usage one of the riskiest, as
changing the return type (and not having to check the referring code)
could be very bad news, and very hard to debug - particulary if it
compiles but suddenly works differently.

If it compiles then you are going to have exactly the same situation as if
you just automatically changed the type name. Nobody is actually going to
check all call sites for semantic changes unless they know that they are
there in which case they can do it explicitly by searching.

As a point of design you should avoid changing the semantics of an operation
without also changing its name. If you stick to this then it will be OK
either way.
 
S

Scott C

Thanks Jon and Nick for your quick responses.

It still seems a bit fishy to me. I'm working my way through
Stroustrup's "The C++ Programming Language" (yes, I know, wrong group)
and he makes a good, language independent comment regarding function
overloading and overloading the return values. I've seen the same
comment made in this ng. One reason (he says) that a function overload
can't be on the return value is that this means a "context" is required,
ie. looking at the function call like

int i = SomeFunc();

would be different from

MyClass c = SomeFunc();

This requirement of a "context" (he said) was undesirable.

var obj = GetSomething();

seems like a nightmare.

Sorry I can't come up with any direct references, the book's at home and
I'm at work.

Jon: I'll check out those references when I get a chance.

Scott
 
N

Nick Hounsome

You are getting confused by a completely separate issue.

There is no overloading on return value in C# or C++ - overloading is just
on parameters.

There is nothing clever going on the compiler is just saving you some
typing.

Consider:

class Y
{
public void YF() {}
}

class X
{
public object F() { return new Y(); }
public Y F(int x) { return new Y(); }
public void G(X x)
{
var v1 = x.F();
var v2 = x.F(2);
v1.YF(); // ERROR: v1 is Object because F() returns object
v2.YF(); // OK: v2 is Y because F(int) returns Y
H(v1); // calls H(Object)
H(v2); // calls H(Y)
}
public void H(Y y){}
public void H(Object o);
}

In non-strict VB (I don't use it so I may be wrong and can't remember the
syntax) you could use something like:

dim v1
v1.YF()

because in this case VB would use reflection to find its runtime type and
call the appropriate method for the supplied arguments. If F() was
{return new string();} then you would get an error at runtime.
 
B

Bruce Wood

No, Scott got it right. Using var in the way you described is like a
poor man's covariant return type. Just for the record, I also agree
that it's a risky use of var. Using interfaces is a far better idea:

ICollection a = x.GetIt();

Sorry, I don't buy the "if it compiles, then it's semantically
equivalent" argument.

"var" works in the case of LINQ because the general class of object
being returned is always the same. The only difference may be in what
columns are present, etc. In that case, it _is_ true that "if it
compiles then it's semantically equivalent." However, in the case of
general class instances it's not, IMHO.
 
F

Fabio Cannizzo

Thanks Nicholas

I got lost when you guys started talking about VB, but I got your tip, which
will do for now. Thanks a lot.

A pity it does not work not for nested thing... i.e. this does not work...
using MickeyInt = Mickey<int>;
using DonaldMickey = Donald<MickeyInt>;

Also a pity it cannot be used with Generic...

But I guess at some point MS will re-introduce these features, togteher with
many of the other great features of C++ they dropped.

F


Nicholas Paldino said:
Fabio,

There is something like it that you can use.

You can do:

using MickeyT = Mickey<T>;

However, T has to be a valid type, you can't use it in a using
statement like that with a type parameter.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Fabio Cannizzo said:
When you use generic, especially if nested, names can become very long.

Is there a way around that, similar to typedef in C?

E.g. something like

class Mickey<T> {}

"typedef" Mickey<T> MickeyT;

Thanks,
Fabio
 
D

Daniel O'Connell [C# MVP]

Bruce Wood said:
No, Scott got it right. Using var in the way you described is like a
poor man's covariant return type. Just for the record, I also agree
that it's a risky use of var. Using interfaces is a far better idea:

I certainly wouldn't consider it close to covariant return types, since the
actual type doesn't change in a descending class(which would be extremely
useful and would use natural polymorphism instead of hacks, same goes for
contravariant parameters). The class still has no methods overloaded on
return types. The range of types the call site will accept grows, but the
range of types returned doesn't. Mild difference I know, still.

At any rate, I still don't like that usage. IMHO var should use a pattern
akin to:

var IDENTIFIER = new EXPRESSION;
or
var IDENTIFIER = LINQ_QUERY;

and nothing else(it'd be nice if this was atleast a warning in the
compiler). Using it to accept any type returned by an expression seems
risky, but I see no problem with using it to shorten construction
expressions(prefer it over using aliases actually, which pushes the actual
type to the top of the file) and for anonymous types. A bit ugly, perhaps,
but I think we will all learn to deal with that rather rapidly. Using var
for quick and dirty, "type this as what this method returns" is a dangerous
road, IMHO.
 

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