Restricting or constraining parameters

  • Thread starter Thread starter Mark Broadbent
  • Start date Start date
M

Mark Broadbent

C# 's type checking is great, but one thing which has reared it's ugly head
is the possibility of causing an unhandled Exception because you've passed
in an un-initialised or empty object. In some cases this might be a valid
operation in your class but many times it might not.

Say for instance I have a class Widget with only one constructor...

class Widget{
private string widgetName;
public Widget( string widgetname) {
widgetName = widgetname;
}
public string WidgetName{
get {return widgetName}
}
}

Now operationally an instance of this class will be ok if it is created like
so...
Widget myWidget = new Widget(null);
or
Widget myWidget = new Widget("");

But logically speaking it would be a nonsense. We might also expand on the
implementaion of the class so that the workings of it depend on the
constructor string being i) Initialised and ii) Having at least one
character otherwise an unhandled/ unexpected exception might be thrown. For
instance class members might (and indeed in most cases) assume that the
widgetName private variable is set to a value.

As far as I am aware, there is no current mechanism in place to prevent this
happening (or in otherwords to programatically constrain parameters so that
the C# compiler reports back any invalid inputs). The only way around this
is for each method that this might be an issue to check the parameters at
the mehtod begining and throw a custom exception to indicate this "breaking
of the rules" (but of course this issue then becomes a run-time thing).

.....So my questions are these

i.
Is there a better mechanism currently in place to already do this?
(e.g. maybe an attribute, for instance something like this
[parameter("widgetname", Constrained = true, Constraint.Length > 0)]
public Widget( string widgetname)

ii.
If this is not a feature of the current runtime, is something like it going
to be available in 2.0 or higher?

Thanks,

Br,

Mark.
 
There is no way around this.
Just check if it is a null reference, and if it is, throw an
ArgumentNullException:
if (null == widgetname)
throw new ArgumentNullException("widgetname");
To extend for also checking an empty string:
if (null == widgetname || 0x0 < widgetname.Length)
throw null == widgetname
? new ArgumentNullException("widgetname")
: new ArgumentException("Cannot be an empty string.", "widgetname");

I believe .NET 2.0 will introduce static method String.IsNullOrEmpty
to simplify this(?).
 
Sorry;
if (null == widgetname || 0x0 < widgetname.Length)
should be
if (null == widgetname || 0x0 == widgetname.Length)

--
Regards,
Dennis JD Myrén
Oslo Kodebureau
Dennis Myrén said:
There is no way around this.
Just check if it is a null reference, and if it is, throw an
ArgumentNullException:
if (null == widgetname)
throw new ArgumentNullException("widgetname");
To extend for also checking an empty string:
if (null == widgetname || 0x0 < widgetname.Length)
throw null == widgetname
? new ArgumentNullException("widgetname")
: new ArgumentException("Cannot be an empty string.", "widgetname");

I believe .NET 2.0 will introduce static method String.IsNullOrEmpty
to simplify this(?).

--
Regards,
Dennis JD Myrén
Oslo Kodebureau
Mark Broadbent said:
C# 's type checking is great, but one thing which has reared it's ugly head
is the possibility of causing an unhandled Exception because you've passed
in an un-initialised or empty object. In some cases this might be a valid
operation in your class but many times it might not.

Say for instance I have a class Widget with only one constructor...

class Widget{
private string widgetName;
public Widget( string widgetname) {
widgetName = widgetname;
}
public string WidgetName{
get {return widgetName}
}
}

Now operationally an instance of this class will be ok if it is created like
so...
Widget myWidget = new Widget(null);
or
Widget myWidget = new Widget("");

But logically speaking it would be a nonsense. We might also expand on the
implementaion of the class so that the workings of it depend on the
constructor string being i) Initialised and ii) Having at least one
character otherwise an unhandled/ unexpected exception might be thrown. For
instance class members might (and indeed in most cases) assume that the
widgetName private variable is set to a value.

As far as I am aware, there is no current mechanism in place to prevent this
happening (or in otherwords to programatically constrain parameters so that
the C# compiler reports back any invalid inputs). The only way around this
is for each method that this might be an issue to check the parameters at
the mehtod begining and throw a custom exception to indicate this "breaking
of the rules" (but of course this issue then becomes a run-time thing).

....So my questions are these

i.
Is there a better mechanism currently in place to already do this?
(e.g. maybe an attribute, for instance something like this
[parameter("widgetname", Constrained = true, Constraint.Length > 0)]
public Widget( string widgetname)

ii.
If this is not a feature of the current runtime, is something like it going
to be available in 2.0 or higher?

Thanks,

Br,

Mark.
 
that's what I feared Dennis. I'm already doing the checking, but it would be
lovely to do something cleaner that functions at design time.

Any MVP's out there that can suggest this to Anders?
....or I will if I can find the email address for ms c# suggestions....anyone
know this?

Thx Dennis.

Br,

Mark.

Dennis Myrén said:
There is no way around this.
Just check if it is a null reference, and if it is, throw an
ArgumentNullException:
if (null == widgetname)
throw new ArgumentNullException("widgetname");
To extend for also checking an empty string:
if (null == widgetname || 0x0 < widgetname.Length)
throw null == widgetname
? new ArgumentNullException("widgetname")
: new ArgumentException("Cannot be an empty string.", "widgetname");

I believe .NET 2.0 will introduce static method String.IsNullOrEmpty
to simplify this(?).

--
Regards,
Dennis JD Myrén
Oslo Kodebureau
Mark Broadbent said:
C# 's type checking is great, but one thing which has reared it's ugly head
is the possibility of causing an unhandled Exception because you've passed
in an un-initialised or empty object. In some cases this might be a valid
operation in your class but many times it might not.

Say for instance I have a class Widget with only one constructor...

class Widget{
private string widgetName;
public Widget( string widgetname) {
widgetName = widgetname;
}
public string WidgetName{
get {return widgetName}
}
}

Now operationally an instance of this class will be ok if it is created like
so...
Widget myWidget = new Widget(null);
or
Widget myWidget = new Widget("");

But logically speaking it would be a nonsense. We might also expand on the
implementaion of the class so that the workings of it depend on the
constructor string being i) Initialised and ii) Having at least one
character otherwise an unhandled/ unexpected exception might be thrown. For
instance class members might (and indeed in most cases) assume that the
widgetName private variable is set to a value.

As far as I am aware, there is no current mechanism in place to prevent this
happening (or in otherwords to programatically constrain parameters so that
the C# compiler reports back any invalid inputs). The only way around this
is for each method that this might be an issue to check the parameters at
the mehtod begining and throw a custom exception to indicate this "breaking
of the rules" (but of course this issue then becomes a run-time thing).

....So my questions are these

i.
Is there a better mechanism currently in place to already do this?
(e.g. maybe an attribute, for instance something like this
[parameter("widgetname", Constrained = true, Constraint.Length > 0)]
public Widget( string widgetname)

ii.
If this is not a feature of the current runtime, is something like it going
to be available in 2.0 or higher?

Thanks,

Br,

Mark.
 
Dennis Myrén said:
Sorry;
if (null == widgetname || 0x0 < widgetname.Length)
should be
if (null == widgetname || 0x0 == widgetname.Length)

Or, more readably IMO

if (widgetname == null || widgetname.Length == 0)

The "constants on the left" safety-net against typos in C isn't needed
in C# :)
 
Mark Broadbent said:
that's what I feared Dennis. I'm already doing the checking, but it would be
lovely to do something cleaner that functions at design time.

Any MVP's out there that can suggest this to Anders?
...or I will if I can find the email address for ms c# suggestions....anyone
know this?

There's (e-mail address removed), I seem to remember. I haven't had any
contact with Anders myself, I'm afraid. It would really want to be part
of a much bigger push towards pre/post conditions etc.
 
Thanks Jon. Sql server has it's own (e-mail address removed) I thought their
might be a csharp one -but couldnt find it. Will probably use your ms one
(you never know someone might listen!).
 
Mark,

Just as a minor point, new Widget(null) wouldn't work; it'd have to be new
Widget((string)null).

I'm confused as to how the compiler, at compile time, is going to reliably
catch any constrained inputs other than if you happen to pass in a constant
or enum. In practice, don't you find that you're passing variables most of
the time anyway? And that will still need runtime checking.

--Bob
 
Bob Grommes said:
Just as a minor point, new Widget(null) wouldn't work; it'd have to be new
Widget((string)null).

Why, out of interest?
I'm confused as to how the compiler, at compile time, is going to reliably
catch any constrained inputs other than if you happen to pass in a constant
or enum. In practice, don't you find that you're passing variables most of
the time anyway? And that will still need runtime checking.

That was my thought, too. Still, a way to automate runtime checking
would be nice - it can get very tedious writing out

if (arg==null)
{
throw new ArgymentNullException("arg");
}

etc
 
Jon Skeet said:
There's (e-mail address removed), I seem to remember. I haven't had any
contact with Anders myself, I'm afraid. It would really want to be part
of a much bigger push towards pre/post conditions etc.

You may also want to look into the new product feedback center.

http://lab.msdn.microsoft.com/productfeedback/

If you look, you may find other people who have posted solutions similar to
yours, inwhich case you can vote on them, If not, you can post your own. You
are welcome to post your link back here if you make a suggestion, asfar as
I'm concerned, if its good enough I will atleast vote for it.

One similar is Bruno's Non-Nullable types:
http://lab.msdn.microsoft.com/produ...edbackid=42aca242-d29c-4c22-8fdd-6613f6b2a2d9
 
Jon Skeet said:
Why, out of interest?

Well, I'll be damned. I've been in the habit of doing stuff like:

return (string)null; // in a string method

.... because the compiler (I swear) once nattered at me about leaving off the
cast; it was too ambiguous. So I got into the habit of doing this
everyplace and never revisited it. But just now I did:

private string Foo(string s) {
return null;
}

.... and it worked. Furthermore, a call of Foo(null) to this method also
worked.

"null" is a magic value, not a type; I can understand the compiler not
liking it. But either I was hallucinating back in the days of VS 2002 / CLR
1.0, or they have added a little implicitizing to the compiler since then.

Anyway -- damn clever, Jon. Almost anyone else would have said, "nuh-uh, it
works fine". You said "Why, out of interest?" and made me do all the heavy
lifting! ;-)
it can get very tedious writing out

if (arg==null)
{
throw new ArgymentNullException("arg");
}

etc

This is true. At least in the abstract, I rather like Bertrand Meyer's
concept of "contracts", which formalizes this stuff syntactically by forcing
you to write contraints in a dedicated code block. And if memory serves, he
has some syntax for declaring constraints that makes it possible for the IDE
generate some rather nice docs right from the code. But to get this one has
to resort to Eiffel.NET, and for some reason no one is breaking down my door
looking for me to do projects in Eiffel.

--Bob
 
Bob Grommes said:
Well, I'll be damned. I've been in the habit of doing stuff like:

return (string)null; // in a string method

... because the compiler (I swear) once nattered at me about leaving off the
cast; it was too ambiguous. So I got into the habit of doing this
everyplace and never revisited it. But just now I did:

private string Foo(string s) {
return null;
}

... and it worked. Furthermore, a call of Foo(null) to this method also
worked.

"null" is a magic value, not a type; I can understand the compiler not
liking it. But either I was hallucinating back in the days of VS 2002 / CLR
1.0, or they have added a little implicitizing to the compiler since then.

I suspect you may have been trying to use it in an overloading
situation where no one type was most specific. For example:

using System;
using System.Collections;

class Test
{
static void Main()
{
Foo(null);
}

static void Foo(ArrayList al)
{
}

static void Foo(string s)
{
}
}
Anyway -- damn clever, Jon. Almost anyone else would have said, "nuh-uh, it
works fine". You said "Why, out of interest?" and made me do all the heavy
lifting! ;-)

I just wondered whether I'd missed something :)
This is true. At least in the abstract, I rather like Bertrand Meyer's
concept of "contracts", which formalizes this stuff syntactically by forcing
you to write contraints in a dedicated code block.

Contract programming is the phrase I was grasping for earlier.
Unfortunately I had a nine-month-old baby demanding my attention...
And if memory serves, he
has some syntax for declaring constraints that makes it possible for the IDE
generate some rather nice docs right from the code. But to get this one has
to resort to Eiffel.NET, and for some reason no one is breaking down my door
looking for me to do projects in Eiffel.

Indeed. Attributes would provide quite reasonable syntax for all of
this, but I don't know whether we're ever likely to see them used for
that purpose.
 
And if memory serves, he
Indeed. Attributes would provide quite reasonable syntax for all of
this, but I don't know whether we're ever likely to see them used for
that purpose.

I disagree, I don't think you should ever write code in an attribute. I do
suspect, however, that generic constraints syntax can easily be extended to
parameters as well. Of course, I've pitched that before, several times.
 
Hi Bob....

Bob Grommes said:
Mark,

Just as a minor point, new Widget(null) wouldn't work; it'd have to be new
Widget((string)null).

Jons already corrected you on this bit so I wont bother ...but having to
cast a null to the type you are comparing it with would be crazy since null
has theoretically no type (but maybe you did see this in a very early
incarnation of C#).

I'm confused as to how the compiler, at compile time, is going to reliably
catch any constrained inputs other than if you happen to pass in a
constant

Yes I suppose you are right to a degree here although it would be simple
for the compiler to check static params, but I guess this will provide
limited benefit. However at runtime there would in my opinion be great
benefit. You are providing guarantees to the code using the params.

or enum. In practice, don't you find that you're passing variables most of
the time anyway? And that will still need runtime checking.

Yes. Having thought about this situation more I guess the provision of
constraints will boil down to what Jon mentions ... saving writing tedious
code to provide the runtime checking (which can't be bad). Additionally this
may be used for GUI style features.
For instance the constraints could provide a more detailed automatic
documentation of the method's parameters and their usage. Another usage
might be for unit testers, where the unit testing app can automatically see
what a parameter should be able to do and only pass in relevant test data
that is not "constrained" -which would possibly simplify things slightly.

But more important for me is the fact that by setting constraints to the
parameters prevents (or reduces) the possibility that the parameter checking
code is incorrect -since the more code that has to be written increases the
chance of potential logic errors.


Thanks everyone for all your replies,

Br,

Mark.
 
These are my ideas for possible contraints which returns in
ArgumentExceptions if failed:

[Constraint(s.Lenght >= 1, s.Lenght < 256)] // MinLenght and MaxLenght
works for every type of collection
[Constraint(s!=null, num>=0, Inherit = true)] // this contraint will be
inherited by derived classes
[Constraint(return, MinValue = 1, MaxValue = 0xfffff)] // constraint on
return value
int GetFoo(string s, int num)
{
// some code
}

The constraints can optionally be inherited by derived classes.
 
cody said:
These are my ideas for possible contraints which returns in
ArgumentExceptions if failed:

[Constraint(s.Lenght >= 1, s.Lenght < 256)] // MinLenght and MaxLenght
works for every type of collection
[Constraint(s!=null, num>=0, Inherit = true)] // this contraint will be
inherited by derived classes
[Constraint(return, MinValue = 1, MaxValue = 0xfffff)] // constraint on
return value
int GetFoo(string s, int num)
{
// some code
}

Yuck, attributes, ;)

I'd rather see
int GetFool(string s, int num)
where return > 1 && return < 0xffff
where s != null
where num >= 0
{

}
 
Back
Top