 |
|
 |
quite logical and helpfull
|
|
|
|
 |
|
 |
What's wrong with using the coalesce operator when this is a problem? void MyFunction(string myString) { Debug.Print(myString ?? ""); }
|
|
|
|
 |
|
 |
Well, when this article was written (2004) the Coalesce operator didn't exist in C#.
Although it certainly helps in these situations, it still relies on the developer remembering to use it; the point of this article was to reduce error rates which is best done by techniques that are 'transparent' and don't require the developer to have to remember to perform any additional actions when using the variable/property.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
class Node
{
Node left;
Node right;
}
Node tree;
|
|
|
|
 |
|
 |
OK I think I understand your question: you use null to mark the end of the recursive branch right?
You're basically using null as a sentinel[^], so you could use the Null Object Pattern[^] as a sentinel instead.
It can add a lot of overhead, but if its part of a larger project or framework its probably worth it.
Herbie
-- modified at 11:58 Friday 18th August, 2006
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
Hey Dr, I used to be in biology, too. Thanks for some useful ideas. There's a problem with the sentence "However, you must also cope with the possibility that the user of the object passes a null back in to the property. Therefore you must catch this and convert it to a null." Don't you mean "convert it to String.Empty"?
Peter Delmonte
|
|
|
|
 |
|
 |
Oops. I'll get around to fixing that at some point in the next few (busy) days.
But I should point out the end disclaimer: "Any spelling mistakes are purely the readers reasonability.". So I guess it's probably your fault .
Thanks for the pointer.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
HI! I need your help, Mr.Herbie, I have to do Pascal's code for an memory game, for my university. (I'm from Spain)
The code has mistakes and I will be very happy if you correct them.
program practica3(input,output);
uses crt,dos;
(* Definicion de constantes *)
const NUMFIL=2;
NUMCOL=2;
JUGADOR1=1;
JUGADOR2=2;
(* Definicion de variables *)
var x,y:char;
fila1,fila2,columna1,columna2,pos,puntuacion,i,j,r:integer;
(* Definicion de tipos *)
type tipoTabla = array (.1..NUMFIL,1..NUMCOL.) of char;
type tipoAuxiliar = array (.1..NUMFIL.) of char;
(** inicializarJuego(tabla,marcador) **)
(** Inicializa el tablero y los marcadores que deben mostrarse **)
procedure inicializarJuego(var tablero:tipoTabla;var fil,col,marcador:integer);
var quedan:array(.1..NUMFIL+NUMCOL.) of integer;
begin
randomize;
for i:=1 to NUMFIL*NUMCOL do
quedan[i]:=i;
for i:=NUMFIL*NUMCOL downto 1 do
begin
r:=random(i)+1;
pos:=quedan[r];
quedan[r]:=quedan[i];
fil:=pos div NUMFIL+1;
col:=pos mod NUMFIL;
tablero[fil,col]:= chr(trunc((64+i+1)/2));
end;
begin
tablero[fil,col]:=chr(32);
for i:=1 to NUMCOL do
for i:=1 to NUMFIL do
begin
i:=fil;
if col<>0 then
i:=col
else
i:=NUMCOL;
if x=y then
tablero[fil,col]:=char(249)
else
tablero[fil,col]:=chr(32);
end;
end;
(** Marcador **)
for j:=JUGADOR1 to JUGADOR2 do
begin
j:=1;
puntuacion:=0;
if x=y then
begin
writeln('Acierto');
puntuacion:=(puntuacion+1);
writeln(puntuacion);
if j=JUGADOR1 then
j:=JUGADOR1
else
j:=JUGADOR2
end;
begin
writeln('Fallo');
puntuacion:=puntuacion;
writeln(puntuacion);
if j=JUGADOR1 then
j:=(JUGADOR1+1)
else
j:=(JUGADOR2-1);
end;
mostrartablero(tablero);
end;
(** Procedimiento para mostrar tablero **)
procedure mostrartablero (var tablero:tipotabla);
begin
for i:=1 to NUMCOL do
begin
col:=i;
for i:=1 to NUMFIL do
fil:=i;
end;
(** leerCasilla(NUMFIL,NUMCOL;var fil,col:integer **)
(** Lee las coordenadas introducidas del tablero y las valida **)
procedure leerCasilla(const NUMFIL,NUMCOL;var fil,col:integer);
begin
writeln ('Escriba la coordenada de la fila');
readln (fil);
while fil>NUMFIL or col>NUMCOL do
begin
writeln ('Error.La coordenada elegida es erronea');
writeln ('Escriba la coordenada de la fila');
readln (fil)
end;
writeln ('Escriba la coordenada de la columna');
readln (col);
while fil>NUMFIL or col>NUMCOL do
begin
writeln ('Error.La coordenada elegida es erronea');
writeln ('Escriba la coordenada de la columna');
readln (fil)
end;
pos:=[fil,col];
end;
(** Modulo principal,cuerpo del programa y llamada a los modulos **)
begin
repeat
begin
mostrarTablero(tablero);
leerCasilla(fil,col);
x:=pos;
leerCasilla(fil,col);
y:=pos;
inicializarJuego(tablero,fil,col,marcador);
end;
until puntuacion:=(NUMFIL+NUMCOL) div 2
readln;
end;
THANKS!!!!!!
|
|
|
|
 |
|
 |
Why is this posted here?? Maybe you should be trying to a website dealing with Pascal... or at least something halfway relevant to your project.
Adam Clauss
cabadam@tamu.edu
|
|
|
|
 |
|
 |
How can we check Date Values are null?
|
|
|
|
 |
|
 |
Well, because DateTime is a value type, you can't check for null. You can get around that by initializing it to DateTime.MinValue and then checking for it instead of null.
Regards
Senthil
_____________________________
My Blog | My Articles | WinMacro
|
|
|
|
 |
|
 |
Well, the DateTime class has no implicit null value so you have to invent your own scheme. There are some libraries out there that create 'Nullable types', and C#2 will have built in nullable types[^].
There is an article on CodeProject about using a nullable DateEdit control[^] which might give you some ideas for nullable dates too.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
Good article. After reading through it, the idea dawned on me that there could be a middle course between the memory drawback of the solution in this article and that for me quite a bit unhandy NullObject design pattern.
You would "only" have to set one static field in each one of your classes which would hold a new instance of itself, to which you would refer everytime a null value is passed, instead of creating new instances overly and overly again.
An example:
class MyClass
{
public static MyClass New = new MyClass();
private OtherClass _other = OtherClass.New; // instead of null
public OtherClass Other
{
get { return _other; }
set { _other = (value == null) ? OtherClass.New : value; }
}
}
class OtherClass
{
public static OtherClass New = new OtherClass(); // instead of null
// ...
}
Thus, null (or new, or empty) objects of a certain class would always point to the same fresh instance, saving a lot of memory, and after all, also logically they indeed can be seen as being the same, in my humble opinion.
Of course, considering better design, that static "New" field (well, call it differently if it disturbs you) should be "interfaced".
|
|
|
|
 |
|
 |
I'm pleased that my article has prompted good responses. That's the reason I like publishing on CodeProject.
The point of an article (as far as I'm concerned) is to make people think and question what they are reading. More importantly (from a selfish point of view) these responses make me think and question my own article content.
Thank you to the posters so far, and I encourage everybody and anybody to put in their opinion.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
Dr. Herbie,
while I (think I) can see from where you're comming from, there are two major drawbacks with your approach. (In the following I use the term "NullObject" for your approach.)
First of all, instead of creating a new NullObject instance each time, in most cases it might be a better solution to use a singleton pattern or a static instance for the NullObject. (This is also mentioned in the reference you gave on discussing the NullObject Pattern.)
The second problem is with your motivation of use of such constructs. You are advocating it way too enthusiatically. Note that Woolf explicitly names situations where one can live with stubs or stub-like behaviour.
Typically, null is assigned to variables to indicate uninitialized or unassigned state, including detaching an instance from a variable, or to indicate a failure of some operation (for example, malloc(3)).
Consider serializing a string instance str to a stream: With a string value of "foo" some would expect some representation of "foo" to be emitted to the target stream. But what if str is null? Clearly, you have to check for str being equal to your NullObject to react to this situation. At this moment, NullObject pattern has been rendered useless.
Further on, you mention avoidance of NullPointerExceptions as a reason for NullObject pattern use. This is inherently dangerous style, because you do not remove the cause (uninitialized variables or bad operation result) but the sympton. While you might get along with this in many cases, you sacrifice correctness of your code, because such exceptions indicate a potential problem with your code.
Bye,
Martin Friedrich
|
|
|
|
 |
|
 |
Martin Friedrich wrote:
singleton pattern or a static instance for the NullObject
That is actually what I had intended to mean, for reasons of memory usage (which is the context I mentioned the NullObject) but I should have been explicit on that one.
Martin Friedrich wrote:
Woolf explicitly names situations where one can live with stubs or stub-like behaviour
I hate to sound arrogant, but I disagree with Woolf -- I do not believe there should ever be stub-like behaviour; it confises programmers (IMHO )
Martin Friedrich wrote:
Typically, null is assigned to variables to indicate uninitialized or unassigned state, including detaching an instance from a variable, or to indicate a failure of some operation (for example, malloc(3)).
Aargh! No one using .NET should ever use a null to indicate a failure, you ahould use an Exception. And malloc? I haven't used malloc for years!
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
Martin Friedrich wrote:
Typically, null is assigned to variables to indicate uninitialized ... state
I forgot to state in the previous reply that as far as defensive programming is concerned, an uninitialised variable is a bug waiting to happen.
The article was about improving code robustness. The cost in this case was increased memory usage. I write business applications for validated environments where code stability and robustness are far more important than memory footprint. I would say that for the majority of desktop applications this is the case (even when not in a validated environment), as memory is cheap enough that a few extra bytes of memory are easily expendable to gain more stable software.
Many people will counter this argument with 'if the software was written properly you wouldn't be worried about stability'. While this is true to some extent, many software systems are too large to have that degree of confidence and requiure teams of programmers to write then, which carries an intrinsic increase in the chances of bugs through mis-communication within the team leading to mis-use of code.
My general philosophy is:
Applications need to be stable, robust, flexible, and maintainable, so don't worry too much about memory or (to a certain extent) speed.
Simulations and calculation-based software needs to be fast, so don't worry too much about memory or code flexibility.
Drivers need to be small and fast and stable, worry about everything. I don't write drivers, I leave that to the real bit-heads.
I believe that people's opinions about the use of null is divided based on the type of software they usually write.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
Hi, Dr. Herbie!
Dr. Herbie wrote:
My general philosophy is:
Applications need to be stable, robust, flexible, and maintainable, so don't worry too much about memory or (to a certain extent) speed.
Simulations and calculation-based software needs to be fast, so don't worry too much about memory or code flexibility.
Drivers need to be small and fast and stable, worry about everything. I don't write drivers, I leave that to the real bit-heads.
You are right in some way. Quite often, robustness and speed/memory issues have to be traded against each other. It's efficiency that has to be paramount - last year I observed implementation of some component based system and the robust variant did take about up to half a second for each transaction. "Moving" that robustness to the parts where it was really needed, did speed up the whole thing considerably.
Dr. Herbie wrote:
I believe that people's opinions about the use of null is divided based on the type of software they usually write.
You can bet on that!
Bye,
Martin Friedrich
|
|
|
|
 |
|
 |
Dr Herbie wrote:
Aargh! No one using .NET should ever use a null to indicate a failure, you ahould use an Exception. And malloc? I haven't used malloc for years!
I disagree with this - I think it is perfectly acceptable to use null to indicate a 'normal and expected' failure, while Exception classes should be used to indicate 'abnormal' errors. In many circumstances you want to be able to continue with your code execution path in spite of errors. Using null return results allows you to do this efficiently - otherwise you would have to surround just about every function call in a try/catch block which IMO only reduces code readability.
-mdb
|
|
|
|
 |
|
 |
hi michael,
there's an approach that you throw an exception for an error (bug) but you should never get there. if you did, the exception indicates that this is truly a bug.
how can you prevent it? by a simple if statement before the method call.
check it out:
http://msdn.microsoft.com/en-us/library/ms229030.aspx[^]
|
|
|
|
 |
|
 |
Hi to all,
for my part, although it's tempting to fill the code with =String.Empty; or =""; (wich is almost the same thing, as string immutability permits string sharing at compile time), I think that it is important to keep the general distinction between declaration and intialization ('general' means that I use the default values when I need them). And if you are looking for pragmatic and laziness reasons, take a look at the memory management impact of your method, especially when you tend to apply it to non value types.
Jeff
|
|
|
|
 |
|
 |
Anonymous wrote:
take a look at the memory management impact of your method
I did mention memory impact in passing, before referencing the NullObject pattern. I had intended this article to go into the 'beginners' section as it emphasised robustness over everything else. I am currently working on frameworks for use by other programmers so I am particularly interested in techniques that emphasise ease of use. If memory management becoes a problem, then I'll go and change things.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |
|
 |
The upcoming String.IsNullOrEmpty() method could help solve part of the problem.
|
|
|
|
 |
|
 |
A handy static func, that accepted a string and returned string.Empty if it's null would help clean up all your null checks.
mMyString = isNull(value);
it beats
if (value != null)
{
mMyString = value;
}
else
{
mMyString = string.Empty;
}
[worldspawn]
|
|
|
|
 |
|
 |
That's a good suggestion.
I won't change the code, though. I want to keep it simple.
Dr Herbie
Remember, half the people out there have below average IQs.
|
|
|
|
 |