473,785 Members | 2,396 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

(Delphi-like) Limited-bounds-types?

As far as I can see, there is no similar way of replicating the
following Delphi-code in C#... Is that true?

type
IntRange = -5..5;
CharRange = 'a'..'z';

TColors = (Red, White, Green, Blue, Yellow);
ColorRange = White..Blue;

Jan 9 '06
21 1964
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
Generics doesn't really do much here (yes, compile time checking against
the type passed in is nice)
It also prevents boxing.
but I think that the thing the OP is trying to
get at is that he doesn't want to perform a check manually, he wants to say
somehow that this is his range, and have the runtime enforce it.


Well, I'm not sure I see much difference between:

ColorRange = White..Blue;
and
Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);

(I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it
doesn't - I need to check the spec to see why.)

The former is certainly neater, but you still get to find out
inclusivity etc - and it probably wouldn't be too hard to give it a bit
more functionality if required.

Maybe I'm missing some more functionality - but all the examples given
can be done with the Range type I gave.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 9 '06 #11
Jon,

I'm not an expert on Delphi, but my impression is that the OP wanted
something more. Yes, the range class does work, but that's not the point.

With context bound objects, you can do something like:

public void MyFunction([Range(0, 5)] int value)
{
// Do something with value here.
// NO need to check against range, since it will have
// already been checked by the context bound object.
}

This is a ficticuous context bound attribute, used to display the point.
This way, his function can assume the check passed, otherwise, the
interception code which the Range attribute handles would throw an
exception.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
Generics doesn't really do much here (yes, compile time checking
against
the type passed in is nice)


It also prevents boxing.
but I think that the thing the OP is trying to
get at is that he doesn't want to perform a check manually, he wants to
say
somehow that this is his range, and have the runtime enforce it.


Well, I'm not sure I see much difference between:

ColorRange = White..Blue;
and
Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);

(I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it
doesn't - I need to check the spec to see why.)

The former is certainly neater, but you still get to find out
inclusivity etc - and it probably wouldn't be too hard to give it a bit
more functionality if required.

Maybe I'm missing some more functionality - but all the examples given
can be done with the Range type I gave.

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

Jan 9 '06 #12
PRECISELY!

Wouldn't it be nice to have such (easily applicable) functionality in
C#?

Nicholas Paldino [.NET/C# MVP] wrote:
Jon,

I'm not an expert on Delphi, but my impression is that the OP wanted
something more. Yes, the range class does work, but that's not the point.

With context bound objects, you can do something like:

public void MyFunction([Range(0, 5)] int value)
{
// Do something with value here.
// NO need to check against range, since it will have
// already been checked by the context bound object.
}

This is a ficticuous context bound attribute, used to display the point.
This way, his function can assume the check passed, otherwise, the
interception code which the Range attribute handles would throw an
exception.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
Generics doesn't really do much here (yes, compile time checking
against
the type passed in is nice)


It also prevents boxing.
but I think that the thing the OP is trying to
get at is that he doesn't want to perform a check manually, he wants to
say
somehow that this is his range, and have the runtime enforce it.


Well, I'm not sure I see much difference between:

ColorRange = White..Blue;
and
Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);

(I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it
doesn't - I need to check the spec to see why.)

The former is certainly neater, but you still get to find out
inclusivity etc - and it probably wouldn't be too hard to give it a bit
more functionality if required.

Maybe I'm missing some more functionality - but all the examples given
can be done with the Range type I gave.

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


Jan 9 '06 #13
matko,

Unfortunately, you would have to do something with ContextBoundObj ects
in order to do this. It will hinder performance, so it is not a feasibile
solution for this kind of thing (since it would be done so often).

However, if you want more information on this, check out the following
MSDN magazine article:

http://msdn.microsoft.com/msdnmag/is...ContextsinNET/
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"matko" <ma*****@gmail. com> wrote in message
news:11******** **************@ g44g2000cwa.goo glegroups.com.. .
PRECISELY!

Wouldn't it be nice to have such (easily applicable) functionality in
C#?

Nicholas Paldino [.NET/C# MVP] wrote:
Jon,

I'm not an expert on Delphi, but my impression is that the OP wanted
something more. Yes, the range class does work, but that's not the
point.

With context bound objects, you can do something like:

public void MyFunction([Range(0, 5)] int value)
{
// Do something with value here.
// NO need to check against range, since it will have
// already been checked by the context bound object.
}

This is a ficticuous context bound attribute, used to display the
point.
This way, his function can assume the check passed, otherwise, the
interception code which the Range attribute handles would throw an
exception.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
> Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
>> Generics doesn't really do much here (yes, compile time checking
>> against
>> the type passed in is nice)
>
> It also prevents boxing.
>
>> but I think that the thing the OP is trying to
>> get at is that he doesn't want to perform a check manually, he wants
>> to
>> say
>> somehow that this is his range, and have the runtime enforce it.
>
> Well, I'm not sure I see much difference between:
>
> ColorRange = White..Blue;
> and
> Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);
>
> (I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it
> doesn't - I need to check the spec to see why.)
>
> The former is certainly neater, but you still get to find out
> inclusivity etc - and it probably wouldn't be too hard to give it a bit
> more functionality if required.
>
> Maybe I'm missing some more functionality - but all the examples given
> can be done with the Range type I gave.
>
> --
> Jon Skeet - <sk***@pobox.co m>
> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
> If replying to the group, please do not mail me too

Jan 9 '06 #14
Bingo!

I want the compiler or/and the runtime-environment to detect
bounds-related errors.
That such (limited-bounds) type declaration is allowed in Delphi is
very... pleasant!

Nicholas Paldino [.NET/C# MVP] wrote:
Generics doesn't really do much here (yes, compile time checking against
the type passed in is nice), but I think that the thing the OP is trying to
get at is that he doesn't want to perform a check manually, he wants to say
somehow that this is his range, and have the runtime enforce it.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
Bruce Wood <br*******@cana da.com> wrote:
I don't know much about .NET 2.0 (yet), but couldn't you create an
IntRange struct in .NET 1.1 that would enforce a range? It wouldn't be
too difficult to do, and would incur minimum overhead.

The only downside is that you would have to declare a separate struct
for each base type, and define all of the implicit and explicit casts,
and math operators, etc, for the new struct.

Well... maybe I should qualify that "not too difficult to do": not too
hard on the brain, but lots of typing. :-)


Here's a .NET 2.0 version (and test case). The .NET 1.1 version would
either require boxing or a separate type for each enum etc:

using System;

public class Range<T> where T : struct, IComparable
{
T min, max;

public Range(T min, T max)
{
this.min = min;
this.max = max;
}

public bool Includes(T value)
{
return min.CompareTo(v alue) <= 0 &&
max.CompareTo(v alue) >= 0;
}
}

enum Foo
{
First,
Second,
Third,
Fourth,
Fifth
}

class Test
{
static void Main()
{
Range<Foo> range = new Range<Foo>(Foo. Second, Foo.Fourth);

foreach (Foo f in Enum.GetValues( typeof(Foo)))
{
Console.WriteLi ne ("{0} - {1}", f, range.Includes( f));
}
}
}

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


Jan 9 '06 #15
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
Jon,

I'm not an expert on Delphi, but my impression is that the OP wanted
something more. Yes, the range class does work, but that's not the point.

With context bound objects, you can do something like:

public void MyFunction([Range(0, 5)] int value)
{
// Do something with value here.
// NO need to check against range, since it will have
// already been checked by the context bound object.
}

This is a ficticuous context bound attribute, used to display the point.
This way, his function can assume the check passed, otherwise, the
interception code which the Range attribute handles would throw an
exception.


Ah, right, I'm with you. Yes, that would be handy. There are lots of
things like that which sometimes are part of design-by-contract,
sometimes part of AOP etc. Hopefully Anders is looking into those for
C# 4.0...

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 9 '06 #16
Not from what I have seen. Anders is NOT a big fan of AOP in the least.
Method interception - MAYBE, but AOP, definitely not.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
Jon,

I'm not an expert on Delphi, but my impression is that the OP wanted
something more. Yes, the range class does work, but that's not the
point.

With context bound objects, you can do something like:

public void MyFunction([Range(0, 5)] int value)
{
// Do something with value here.
// NO need to check against range, since it will have
// already been checked by the context bound object.
}

This is a ficticuous context bound attribute, used to display the
point.
This way, his function can assume the check passed, otherwise, the
interception code which the Range attribute handles would throw an
exception.


Ah, right, I'm with you. Yes, that would be handy. There are lots of
things like that which sometimes are part of design-by-contract,
sometimes part of AOP etc. Hopefully Anders is looking into those for
C# 4.0...

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

Jan 9 '06 #17
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote:
Not from what I have seen. Anders is NOT a big fan of AOP in the least.
Method interception - MAYBE, but AOP, definitely not.


Well, that might be due to current implementations , limitations etc. I
suspect he can see the benefits of being able to specify cross-cutting
concerns, etc, even if he's not happy with how it's all done at the
moment.

I wouldn't be surprised if something came out which at least tackled
the same kinds of issues that AOP does, even if it's not immediately
recognisable as an AOP implementation.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 9 '06 #18
Well, as I pointed out you _could_ create a struct to wrap another
value type and then have that struct do the bounds checking on every
assignment, because each assignment from a base type would really be an
implicit conversion operation. It would invovle significant overhead
(every assignment would really be a method call), and it would also be
a heck of a lot of code to write, as you would have to reproduce every
operator, including all implicit and explicit conversions, of the
native type in your struct wrapper.

This isn't just a Delphi thing. I remember this back in 1980 with
Pascal, so it's not as though it's some fancy new AOP-related thing.
It's probably just another of those features that Anders and the C#
team saw as offering some benefits, but not sufficient benefit to
justify adding yet more syntax to the language.

You could ask for the feature, anyway... it's been in enough other
languages (Pascal and now Delphi) that it's obviously not some flash in
the pan.

Jan 10 '06 #19
Oh, sure.
Delphi _is_, more-or-less (more more than less), Pascal.

Anyway, I'd love this to be a part of C#. It's neat and helpful
functionality.

Thanks for all comments ;)

Bruce Wood wrote:
Well, as I pointed out you _could_ create a struct to wrap another
value type and then have that struct do the bounds checking on every
assignment, because each assignment from a base type would really be an
implicit conversion operation. It would invovle significant overhead
(every assignment would really be a method call), and it would also be
a heck of a lot of code to write, as you would have to reproduce every
operator, including all implicit and explicit conversions, of the
native type in your struct wrapper.

This isn't just a Delphi thing. I remember this back in 1980 with
Pascal, so it's not as though it's some fancy new AOP-related thing.
It's probably just another of those features that Anders and the C#
team saw as offering some benefits, but not sufficient benefit to
justify adding yet more syntax to the language.

You could ask for the feature, anyway... it's been in enough other
languages (Pascal and now Delphi) that it's obviously not some flash in
the pan.


Jan 10 '06 #20

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

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.