Abstract class variables question

T

tshad

Using VS 2003, I am trying to take a class that I created to create new
variable types to handle nulls and track changes to standard variable types.
This is for use with database variables. This tells me if a variable has
changed, give me the original and current value, and whether the current
value and original value is/was null or not.

This one works fine but is recreating the same methods over and over for
each variable type.

What I wanted to do was create an Abstract class that did most of the work
and create a class for each variable type that only does what is needed.

I can't seem to get it to work correctly.

Part of it has to do with where to define my actual data variables. I tried
defining them only as objects in the abstract class but that won't work
because the class doesn't know what type of object it is.

The original file (with most variable types cut out is):
******************************************
using System;
using System.IO;

namespace FtsData
{
[Serializable]
public class StringType
{
private string first = ""; //original data
private string data = ""; //current data
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public StringType()
{
}
public StringType(string initial)
{
first = initial;
data = initial;
}

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
data = "";
}

public void SetFirstNull()
{
nullFirst = true;
first = "";
}

// Properties

public string First
{
get { return first; }
set { first = value; }
}

public string Data
{
get { return data; }
set { data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
} // end Class

[Serializable]
public class BoolType
{
private bool first = false; //original data
private bool data = false; //current data
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public BoolType()
{
}

public BoolType(bool initial)
{
first = initial;
data = initial;
changed = false;
}

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
data = false;
}

public void SetFirstNull()
{
nullFirst = true;
data = false;
}

// Properties

public bool First
{
get { return first; }
set { first = value; }
}

public bool Data
{
get { return data; }
set { data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
} // end Class
} // end Namespace

*******************************************

As you can see much if it is identical and can just be done as an object -
but some can't.

I tried this but did get some errors:
*******************************************
using System;
using System.IO;

namespace FtsData
{
public abstract class DataType
{
protected object _first;
protected object _data;
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
_data = "";
}

public void SetFirstNull()
{
nullFirst = true;
_first = "";
}
// Properties

public string First
{
get { return _first; }
set { _first = value; }
}

public string Data
{
get { return _data; }
set { _data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
}

[Serializable]
public class StringType : DataType
{
private string _first = ""; //original data
private string _data = ""; //current data

public StringType()
{
}
public StringType(string initial)
{
_first = initial;
_data = initial;
changed = false;
}

} // end Class

[Serializable]
public class BoolType : DataType
{
private bool _first = false; //original data
private bool _data = false; //current data

public BoolType()
{
}

public BoolType(bool initial)
{
_first = initial;
_data = initial;
changed = false;
}
} // end Class

} // end namespace
********************************************

I assume I need to create the variables in each class (StringType, BoolType,
IntegerType, DecimalType etc).

I also assume that anything that actually needs to explicitly change the
variables to some value, such as strings to "" or bool to false.
I assume I can't access these variables from my Abstract Class definitions.
This is why I was trying to create them as objects, but then they are
separate variables and I would like to do this only one time. But I can't
seem to figure out how to make that work. So the following may also have to
go each class.

public void SetNull()
{
nullData = true;
_data = "";
}

It's possible I may only be able to handle these from the abstract classes:

private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

But I am just trying to find out if I am overlooking something. I am trying
to get this to simplest set of class that I can.

Thanks,

Tom
 
C

Chris Mullins [MVP - C#]

The obvious answer is to switch over to Visual Studio 2005, and .Net 2.0.

The newer version of .Net has deep support of Nullable types, for exactly
the reason you laid out.
http://blogs.msdn.com/ericgu/archive/2004/05/27/143221.aspx

There is qutie a bit of material on this available on the web.

If you can't use .Net 2.0, write back, and hopefully we can figure something
out...

--
Chris Mullins

tshad said:
Using VS 2003, I am trying to take a class that I created to create new
variable types to handle nulls and track changes to standard variable
types. This is for use with database variables. This tells me if a
variable has changed, give me the original and current value, and whether
the current value and original value is/was null or not.

This one works fine but is recreating the same methods over and over for
each variable type.

What I wanted to do was create an Abstract class that did most of the work
and create a class for each variable type that only does what is needed.

I can't seem to get it to work correctly.

Part of it has to do with where to define my actual data variables. I
tried defining them only as objects in the abstract class but that won't
work because the class doesn't know what type of object it is.

The original file (with most variable types cut out is):
******************************************
using System;
using System.IO;

namespace FtsData
{
[Serializable]
public class StringType
{
private string first = ""; //original data
private string data = ""; //current data
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public StringType()
{
}
public StringType(string initial)
{
first = initial;
data = initial;
}

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
data = "";
}

public void SetFirstNull()
{
nullFirst = true;
first = "";
}

// Properties

public string First
{
get { return first; }
set { first = value; }
}

public string Data
{
get { return data; }
set { data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
} // end Class

[Serializable]
public class BoolType
{
private bool first = false; //original data
private bool data = false; //current data
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public BoolType()
{
}

public BoolType(bool initial)
{
first = initial;
data = initial;
changed = false;
}

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
data = false;
}

public void SetFirstNull()
{
nullFirst = true;
data = false;
}

// Properties

public bool First
{
get { return first; }
set { first = value; }
}

public bool Data
{
get { return data; }
set { data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
} // end Class
} // end Namespace

*******************************************

As you can see much if it is identical and can just be done as an object -
but some can't.

I tried this but did get some errors:
*******************************************
using System;
using System.IO;

namespace FtsData
{
public abstract class DataType
{
protected object _first;
protected object _data;
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
_data = "";
}

public void SetFirstNull()
{
nullFirst = true;
_first = "";
}
// Properties

public string First
{
get { return _first; }
set { _first = value; }
}

public string Data
{
get { return _data; }
set { _data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
}

[Serializable]
public class StringType : DataType
{
private string _first = ""; //original data
private string _data = ""; //current data

public StringType()
{
}
public StringType(string initial)
{
_first = initial;
_data = initial;
changed = false;
}

} // end Class

[Serializable]
public class BoolType : DataType
{
private bool _first = false; //original data
private bool _data = false; //current data

public BoolType()
{
}

public BoolType(bool initial)
{
_first = initial;
_data = initial;
changed = false;
}
} // end Class

} // end namespace
********************************************

I assume I need to create the variables in each class (StringType,
BoolType, IntegerType, DecimalType etc).

I also assume that anything that actually needs to explicitly change the
variables to some value, such as strings to "" or bool to false.
I assume I can't access these variables from my Abstract Class
definitions. This is why I was trying to create them as objects, but then
they are separate variables and I would like to do this only one time.
But I can't seem to figure out how to make that work. So the following
may also have to go each class.

public void SetNull()
{
nullData = true;
_data = "";
}

It's possible I may only be able to handle these from the abstract
classes:

private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

But I am just trying to find out if I am overlooking something. I am
trying to get this to simplest set of class that I can.

Thanks,

Tom
 
T

tshad

Chris Mullins said:
The obvious answer is to switch over to Visual Studio 2005, and .Net 2.0.

The newer version of .Net has deep support of Nullable types, for exactly
the reason you laid out.
http://blogs.msdn.com/ericgu/archive/2004/05/27/143221.aspx

There is qutie a bit of material on this available on the web.

If you can't use .Net 2.0, write back, and hopefully we can figure
something out...

I can't go to 2.0. I am looking forward to going to it, but at the moment I
can't. I would still have the same problem as handling the null variables
are not a problem. The (_first and _data) are the real problems.

Also, I am trying to understand Abstract Classes better and this seemed like
a pretty set of classes that I already had working to start with. I would
like to Abstract to simplify my classes as well as make them easier to
maintain.

Thanks,

Tom
--
Chris Mullins

tshad said:
Using VS 2003, I am trying to take a class that I created to create new
variable types to handle nulls and track changes to standard variable
types. This is for use with database variables. This tells me if a
variable has changed, give me the original and current value, and
whether the current value and original value is/was null or not.

This one works fine but is recreating the same methods over and over for
each variable type.

What I wanted to do was create an Abstract class that did most of the
work and create a class for each variable type that only does what is
needed.

I can't seem to get it to work correctly.

Part of it has to do with where to define my actual data variables. I
tried defining them only as objects in the abstract class but that won't
work because the class doesn't know what type of object it is.

The original file (with most variable types cut out is):
******************************************
using System;
using System.IO;

namespace FtsData
{
[Serializable]
public class StringType
{
private string first = ""; //original data
private string data = ""; //current data
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public StringType()
{
}
public StringType(string initial)
{
first = initial;
data = initial;
}

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
data = "";
}

public void SetFirstNull()
{
nullFirst = true;
first = "";
}

// Properties

public string First
{
get { return first; }
set { first = value; }
}

public string Data
{
get { return data; }
set { data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
} // end Class

[Serializable]
public class BoolType
{
private bool first = false; //original data
private bool data = false; //current data
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public BoolType()
{
}

public BoolType(bool initial)
{
first = initial;
data = initial;
changed = false;
}

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
data = false;
}

public void SetFirstNull()
{
nullFirst = true;
data = false;
}

// Properties

public bool First
{
get { return first; }
set { first = value; }
}

public bool Data
{
get { return data; }
set { data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
} // end Class
} // end Namespace

*******************************************

As you can see much if it is identical and can just be done as an
object - but some can't.

I tried this but did get some errors:
*******************************************
using System;
using System.IO;

namespace FtsData
{
public abstract class DataType
{
protected object _first;
protected object _data;
private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

public bool IsNull()
{
return nullData;
}

public bool IsFirstNull()
{
return nullFirst;
}

public void SetNull()
{
nullData = true;
_data = "";
}

public void SetFirstNull()
{
nullFirst = true;
_first = "";
}
// Properties

public string First
{
get { return _first; }
set { _first = value; }
}

public string Data
{
get { return _data; }
set { _data = value; nullData = false; changed = true;}
}

public bool Changed
{
get {return changed;}
set {changed = value;}
}
}

[Serializable]
public class StringType : DataType
{
private string _first = ""; //original data
private string _data = ""; //current data

public StringType()
{
}
public StringType(string initial)
{
_first = initial;
_data = initial;
changed = false;
}

} // end Class

[Serializable]
public class BoolType : DataType
{
private bool _first = false; //original data
private bool _data = false; //current data

public BoolType()
{
}

public BoolType(bool initial)
{
_first = initial;
_data = initial;
changed = false;
}
} // end Class

} // end namespace
********************************************

I assume I need to create the variables in each class (StringType,
BoolType, IntegerType, DecimalType etc).

I also assume that anything that actually needs to explicitly change the
variables to some value, such as strings to "" or bool to false.
I assume I can't access these variables from my Abstract Class
definitions. This is why I was trying to create them as objects, but then
they are separate variables and I would like to do this only one time.
But I can't seem to figure out how to make that work. So the following
may also have to go each class.

public void SetNull()
{
nullData = true;
_data = "";
}

It's possible I may only be able to handle these from the abstract
classes:

private bool nullFirst = false; //original Data null
private bool nullData = false; //current data null
private bool changed = false;

But I am just trying to find out if I am overlooking something. I am
trying to get this to simplest set of class that I can.

Thanks,

Tom
 
P

Peter Duniho

Using VS 2003, I am trying to take a class that I created to create new
variable types to handle nulls and track changes to standard variable types.
This is for use with database variables. This tells me if a variable has
changed, give me the original and current value, and whether the current
value and original value is/was null or not.

This one works fine but is recreating the same methods over and over for
each variable type.

What I wanted to do was create an Abstract class that did most of the work
and create a class for each variable type that only does what is needed.

I can't seem to get it to work correctly.

If I understand your question correctly, you have at least a couple of goals

* To share the repetitive functionality
* To preserve type safety

It's unfortunate that you can't move to 2.0, because writing a generic
class would actually be the natural solution here. Nullable types are
actually a special case of generic class (Nullable<T>), which is why
they came up in Chris's reply but of course they don't support the
other behaviors you want.

I think that with .NET 1.1, you're going to experience at least a
little pain. There's not really what I'd call a "good" way to do this.
That said, it shouldn't be too bad.

The main caveats:

* There's no good way to deal with value types. If you want to use
the same field to store different kinds of data, you have to accept
that value types will be boxed.

* You'll have to perform a cast somewhere.

That said, it seems to me that something like this would at least
approach what you're trying to do:

abstract class DataType
{
protected object _objInitial;
protected object _objCurrent;
private bool _fChanged;

public bool IsNull
{
get { return _objCurrent == null; }
}

public bool IsFirstNull
{
get { return _objInitial == null; }
}

// You could just use the Data property to set the value to null
// as well. I'm not sure this method is really needed.
public void SetNull()
{
_objCurrent = null;
}

// I left out SetFirstNull()...shouldn't the initial value be
// set in the constructor and not touched after initialization?

// Likewise, I left out the setter for the First property
public object First
{
get { return _objInitial; }
}

public object Data
{
get { return _objCurrent; }
set
{
if (value != null)
{
_ValidateType(value);
}
_objCurrent = value;
_fChanged = true;
}
}

// Likewise, I don't think Changed should include a setter
public bool Changed
{
get { return _fChanged; }
}

// This is what deriving classes will define so the type can be checked
abstract protected Type _TypeRequired;

private void _ValidateType(object obj)
{
Type typeRequired = _TypeRequired;

// Depending on how you're using this class, you may instead prefer
// to check for exact type equality. The below simply
requires that
// the passed-in object has the required type it its
inheritance chain.

if (!typeRequired.IsInstanceOfType(obj))
{
throw new ArgumentException("assigned value type of " +
obj.GetType().Name + " is incompatible with
required type of " +
typeRequired.Name);
}
}
}

class BoolType : DataType
{
// Each class defines this so that the base type can validate
the data's type
protected Type _TypeRequired
{
get { return typeof(bool); }
}

// A convenience method so that no casting is needed when you
already have
// a fully typed object
public bool TypedData
{
get { return (bool)Data; }
set { Data = value; }
}
}

class StringType : DataType
{
protected Type _TypeRequired
{
get { return typeof(string); }
}

public string TypedData
{
get { return (string)Data; }
set { Data = value; }
}
}

I provided an example of using it with a value type and with a
reference type. As you can see, they are basically the same. In the
case of the value type (BoolType) the act of setting the value to an
object type boxes the value, and casting the object back to bool
unboxes it.

If the above example doesn't accomplish what you want, then hopefully
it's at least a good starting point for a discussion where you clarify
the need.

Pete
 
P

Peter Duniho

[...]
That said, it seems to me that something like this would at least
approach what you're trying to do:

Sorry...I appear to have left out the constructors. :( Oh
well...hopefully you get the idea and can add that yourself. It
shouldn't be too much of an inconvenience.
 
T

tshad

This looks pretty much like what I am trying to do.

I hadn't thought about using the objects as null instead of using a separate
variable for it.

I did get an error below when working with it:

abstract protected Type _TypeRequired;

gave me an error:

The modifier 'abstract' is not valid for this item

Not sure why that is.

As far as the constructors - I assume I need to set them for each class
something like:
****************************************
class BoolType : DataType
{
public BoolType()
{
}

public BoolType(bool initial)
{
_objInitial= initial;
_objCurrent = initial;
changed = false;
}

// Each class defines this so that the base type can validate the data's
type
protected Type _TypeRequired
{
get { return typeof(bool); }
}

// A convenience method so that no casting is needed when you already have
// a fully typed object
public bool TypedData
{
get { return (bool)Data; }
set { Data = value; }
}
}

class StringType : DataType
{
public StringType()
{
}

public StringType(string initial)
{
_objInitial= initial;
_objCurrent = initial;
changed = false;
}

protected Type _TypeRequired
{
get { return typeof(string); }
}

public string TypedData
{
get { return (string)Data; }
set { Data = value; }
}
}
****************************************

This was the problem I was having before where I have no way of knowing what
type the object is - not sure if it is really a problem however.

In the 2nd constructor, I am setting the object to a type (since that is
defined in the parameter). But what about the first constructor where I am
not passing anything.

Therefore, the object is not pointing at any variable.

Maybe I am missing something. I will look at it some more tomorrow.

Thanks,

Tom
 
P

Peter Duniho

This looks pretty much like what I am trying to do.

I hadn't thought about using the objects as null instead of using a separate
variable for it.

I did get an error below when working with it:

abstract protected Type _TypeRequired;

gave me an error:

The modifier 'abstract' is not valid for this item

Sorry. That's what I (you) get for me just typing in code without
trying it. :)

The proper declaration would be:

abstract protected Type _TypeRequired { get; }

Also, you'll need "override" with the declarations of that property in
the concrete types.
Not sure why that is.

'Cause I need a compiler to keep me honest. :)
As far as the constructors - I assume I need to set them for each class
Yes.

[...]
This was the problem I was having before where I have no way of knowing what
type the object is - not sure if it is really a problem however.

In the 2nd constructor, I am setting the object to a type (since that is
defined in the parameter). But what about the first constructor where I am
not passing anything.

You would use that constructor if the initial value is to be null. But
the concrete type still defines the actual type. So if you're using
the BoolType() constructor, that is only found in the BoolType class,
and the type of the data is bool. Etc.

It's the data class that defines the type, not whatever value you pass
to it in the constructor.
Therefore, the object is not pointing at any variable.

There's no (practical) way to have an object point to a variable. It
can only point to an instance of some data. It's true that when the
data is null, the object points to null and no actual data. But again,
the concrete class has a specific type and that specific type is what
provides type information about the data, even when it's null.

Pete
 
P

Peter Duniho

[...]
I did need to add a method Reset() to reset the _objInitial variable to be
whatever the _objCurrent is at the time as well as change the _fChange to
false.

This is to handle the situations, such as Database updates or inserts, where
we still want to use the same screen but have already updated the data.

That's fine. The class is for your use. You should put the features
you need into it. :)
[...]
Actually, it compiles fine. But the problem is that the compiler won't let
me do the following in my code that calls these objects:

bool test;
BoolType booltemp = new BoolType(false);
booltemp.Data = true;
test = booltemp.Data;
test = booltemp.First;

I get an error on the last 2 lines.

Cannot implicitly convert type 'object' to 'bool'

I assume the method is supposed to handle that - but I don't think the
compiler sees the method.

No, the property I included as a convenience property (sorry for the
misleading comment that says "method" :) ) needs to be used directly
for it to be useful. It doesn't change how the base class properties
behave.

So in your code, you could write this:

test = booltemp.TypedData;

and that would work.

You can also add a similar property for the first value:

public bool TypedFirst
{
get { return (bool)Data; }
set { Data = value; }
}

Then the second of the two lines causing an error would look like:

test = booltemp.TypedFirst;

Note that strictly speaking, the setter for the typed property isn't
required, since the down-cast to Object works automatically with the
base class property. I like having it though, just for the symmetry.

Hope that helps.

Pete
 
T

tshad

Peter Duniho said:
On 2007-11-13 22:42:29 -0800, "tshad" <[email protected]> said:


Also, you'll need "override" with the declarations of that property in the
concrete types.

That fixed it.

I made some changes and agree that I don't need SetNull methods or the
setters for some of the Properties.

I did need to add a method Reset() to reset the _objInitial variable to be
whatever the _objCurrent is at the time as well as change the _fChange to
false.

This is to handle the situations, such as Database updates or inserts, where
we still want to use the same screen but have already updated the data. At
that point, I don't care what the original data was, since the record(s)
have been updated and I now want the current data to match the original data
so I can tell if the data changed so that I can update the records again if
necessary.

I did find that the methods:

// A convenience method so that no casting is needed when you already have
// a fully typed object
public bool TypedData
{
get { return (bool)Data; }
set { Data = value; }
}

doesn't seem to work.

Actually, it compiles fine. But the problem is that the compiler won't let
me do the following in my code that calls these objects:

bool test;
BoolType booltemp = new BoolType(false);
booltemp.Data = true;
test = booltemp.Data;
test = booltemp.First;

I get an error on the last 2 lines.

Cannot implicitly convert type 'object' to 'bool'

I assume the method is supposed to handle that - but I don't think the
compiler sees the method.

Am I missing something?

Here is the code I am using at the moment:
**************************************
C:\VSProjects\DBTypesCSharp2\Form1.cs(93): using System;
using System.IO;

namespace FtsData
{
abstract class DataType
{
protected object _objInitial;
protected object _objCurrent;
private bool _fChanged;

public bool IsNull
{
get { return _objCurrent == null; }
}

public bool IsFirstNull
{
get { return _objInitial == null; }
}

// Reset _objInitial to _objCurrent and changed flag to false to track
// when this variable changes again. This would be necessary if were to
// write out data to a database record and need to track when it changes
again

public void Reset()
{
_objInitial = _objCurrent;
_fChanged = false;
}

public object First
{
get { return _objInitial; }
}

public object Data
{
get { return _objCurrent; }
set
{
if (value != null)
{
_ValidateType(value);
}
_objCurrent = value;
_fChanged = true;
}
}

// Likewise, I don't think Changed should include a setter
public bool Changed
{
get { return _fChanged; }
}

// This is what deriving classes will define so the type can be checked
abstract protected Type _TypeRequired { get; }

private void _ValidateType(object obj)
{
Type typeRequired = _TypeRequired;

// Depending on how you're using this class, you may instead prefer
// to check for exact type equality. The below simply requires that
// the passed-in object has the required type in its inheritance chain.

if (!typeRequired.IsInstanceOfType(obj))
{
throw new ArgumentException("assigned value type of " +
obj.GetType().Name + " is incompatible with required type of " +
typeRequired.Name);
}
}
}

class BoolType : DataType
{
public BoolType()
{
}

public BoolType(bool initial)
{
_objInitial= initial;
_objCurrent = initial;
}

// Each class defines this so that the base type can validate the data's
type
protected override Type _TypeRequired
{
get { return typeof(bool); }
}

// A convenience method so that no casting is needed when you already have
// a fully typed object
public bool TypedData
{
get { return (bool)Data; }
set { Data = value; }
}
}

class StringType : DataType
{
public StringType()
{
}

public StringType(bool initial)
{
_objInitial= initial;
_objCurrent = initial;
}

protected override Type _TypeRequired
{
get { return typeof(string); }
}

public string TypedData
{
get { return (string)Data; }
set { Data = value; }
}
}
}
**************************************

Thanks,

Tom
 
T

tshad

Peter Duniho said:

No, the property I included as a convenience property (sorry for the
misleading comment that says "method" :) ) needs to be used directly for
it to be useful. It doesn't change how the base class properties behave.

So in your code, you could write this:

test = booltemp.TypedData;

and that would work.

You can also add a similar property for the first value:

public bool TypedFirst
{
get { return (bool)Data; }
set { Data = value; }
}

I assume this is supposed to be:

public bool TypedFirst
{
get { return (bool)First; }
set { First = value; }
}

Also, is there any reason you used First instead of _objInitial and Data
instead of _objCurrent? Or was it 6 of one half dozen...?

I am still trying to figure out what the following does. I assume this is a
property. Is there any reason why you need to abstract it?

// This is what deriving classes will define so the type can be checked
abstract protected Type _TypeRequired { get; }

Each of the classes could just do:

// Each class defines this so that the base type can validate the data's
type
protected Type _TypeRequired
{
get { return typeof(bool); }
}

Right?

Or is it to force code to have this in each class to avoid forgetting it?
Then the second of the two lines causing an error would look like:

test = booltemp.TypedFirst;

Note that strictly speaking, the setter for the typed property isn't
required, since the down-cast to Object works automatically with the base
class property. I like having it though, just for the symmetry.

Hope that helps.

It does a lot.

Learned a lot from this.

Thanks,

Tom
 
P

Peter Duniho

I assume this is supposed to be:

public bool TypedFirst
{
get { return (bool)First; }
set { First = value; }
}

Yes, sorry.
Also, is there any reason you used First instead of _objInitial and Data
instead of _objCurrent? Or was it 6 of one half dozen...?

No, I really do prefer to use the property. Performance isn't an
issue, because the C# compiler will inline the property access code if
it can. There are some rare situations where you really do want to
access the field without going through the property code (for example,
a scenario where you're in a method that would be invoked by the
property access itself, it's simpler to just not go through the
property in order to avoid recursion). But for the most part, IMHO it
is better to use the property when you can.

Encapsulation isn't just good for clients of the class; it's good for
the class itself.
I am still trying to figure out what the following does. I assume this is a
property. Is there any reason why you need to abstract it?

Yes, there is.
// This is what deriving classes will define so the type can be checked
abstract protected Type _TypeRequired { get; }

Each of the classes could just do:

// Each class defines this so that the base type can validate the data's
type
protected Type _TypeRequired
{
get { return typeof(bool); }
}

Right?

No, they couldn't. The base class needs to know that this property
exists, because it uses it to validate the type when setting the data.
Without the abstract property, you couldn't write code in the base
class that relies on the property without having the base class be
aware of each and every derived class.
Or is it to force code to have this in each class to avoid forgetting it?

No, it's to force code to have this in each class so that the base
class can include code that the compiler can verify as correct, without
having to have a big switch statement testing the instance's class and
calling the individual types' properties directly.

Try taking the abstract declaration out and see what the compiler does
when you try to recompile.

Pete
 
T

tshad

Peter Duniho said:
Yes, sorry.


No, I really do prefer to use the property. Performance isn't an issue,
because the C# compiler will inline the property access code if it can.
There are some rare situations where you really do want to access the
field without going through the property code (for example, a scenario
where you're in a method that would be invoked by the property access
itself, it's simpler to just not go through the property in order to avoid
recursion). But for the most part, IMHO it is better to use the property
when you can.

Encapsulation isn't just good for clients of the class; it's good for the
class itself.

Makes sense.
Yes, there is.


No, they couldn't. The base class needs to know that this property
exists, because it uses it to validate the type when setting the data.
Without the abstract property, you couldn't write code in the base class
that relies on the property without having the base class be aware of each
and every derived class.

Which was what I was trying to figure out. And this is obviously the answer
as to how the Base Class can tell what the type is.

But I am confused as to how it works.

You actually set _TypeRequired in each class and _ValidateType seems to know
what _TypeRequired is. In _ValidateType, at the line:

Type typeRequired = _TypeRequired;

Before it is actually executed - it seems to know what _TypeRequired is !!!
Yet I can't see where it is actually being set - just defined (either as
abstract or overridden).

I added a line just to break on and see what _TypeRequired is and it knew it
was system.bool. But where did it get set???

private void _ValidateType(object obj)
{
_fChanged = _fChanged;
Type typeRequired = _TypeRequired;

I tried stepping through the code and couldn't see where the Property
_TypeRequired was being set. So at what point is this getting set for the
_ValidateType function to function :)
No, it's to force code to have this in each class so that the base class
can include code that the compiler can verify as correct, without having
to have a big switch statement testing the instance's class and calling
the individual types' properties directly.

Try taking the abstract declaration out and see what the compiler does
when you try to recompile.

Got an error as you expected.

Just out of curiosity - I was wondering why you underscore _ValidateType and
_TypeRequired. I understand why you do it for _objCurrent (memory variable)
and why you use prefix the type (obj - hungarian). But I was wondering
about the other 2.

Thanks,

Tom
 
B

Ben Voigt [C++ MVP]

Which was what I was trying to figure out. And this is obviously the
answer as to how the Base Class can tell what the type is.

But I am confused as to how it works.

You actually set _TypeRequired in each class and _ValidateType seems to
know what _TypeRequired is. In _ValidateType, at the line:

Type typeRequired = _TypeRequired;

Before it is actually executed - it seems to know what _TypeRequired is
!!! Yet I can't see where it is actually being set - just defined (either
as abstract or overridden).

It's a property, not a variable, so it is computed each time it is
referenced by calling the getter. The getter is simply "{ return
typeof(bool); }".
 
P

Peter Duniho

[...]
No, they couldn't. The base class needs to know that this property
exists, because it uses it to validate the type when setting the data.
Without the abstract property, you couldn't write code in the base class
that relies on the property without having the base class be aware of each
and every derived class.

Which was what I was trying to figure out. And this is obviously the answer
as to how the Base Class can tell what the type is.

But I am confused as to how it works.

You actually set _TypeRequired in each class and _ValidateType seems to know
what _TypeRequired is. In _ValidateType, at the line:

Type typeRequired = _TypeRequired;

Before it is actually executed - it seems to know what _TypeRequired is !!!

That's probably just the debugger being clever. Nothing is actually
known until the getter for the property is executed, which doesn't
happen until that assignment is executed (or until the debugger tries
to evaluate the property).
Yet I can't see where it is actually being set - just defined (either as
abstract or overridden).

I added a line just to break on and see what _TypeRequired is and it knew it
was system.bool. But where did it get set???

It's "set" basically as a hard-coded statement in the property
declaration. There's no data storing the value; just a line of code
that always returns the same value.

Because the property is "abstract", it's basically a virtual property,
but without a default implementation (think pure virtual in C++). As a
virtual property, the base class can call it without knowing the
concrete type of the instance, and the override will still be executed
and return the right value.

But the value per se isn't initialized or stored anywhere.
[...]
Just out of curiosity - I was wondering why you underscore _ValidateType and
_TypeRequired. I understand why you do it for _objCurrent (memory variable)
and why you use prefix the type (obj - hungarian). But I was wondering
about the other 2.

Actually, you don't understand why I do it for _objCurrent. :)

I am in the habit of using the underscore prefix for non-public members
of classes. That's what you're seeing there. That applies both to
_objCurrent field as well as methods and properties (like _ValidateType
and _TypeRequired).

Pete
 
T

tshad

Peter Duniho said:
[...]
No, they couldn't. The base class needs to know that this property
exists, because it uses it to validate the type when setting the data.
Without the abstract property, you couldn't write code in the base class
that relies on the property without having the base class be aware of
each
and every derived class.

Which was what I was trying to figure out. And this is obviously the
answer
as to how the Base Class can tell what the type is.

But I am confused as to how it works.

You actually set _TypeRequired in each class and _ValidateType seems to
know
what _TypeRequired is. In _ValidateType, at the line:

Type typeRequired = _TypeRequired;

Before it is actually executed - it seems to know what _TypeRequired is
!!!

That's probably just the debugger being clever. Nothing is actually known
until the getter for the property is executed, which doesn't happen until
that assignment is executed (or until the debugger tries to evaluate the
property).
Yet I can't see where it is actually being set - just defined (either as
abstract or overridden).

I added a line just to break on and see what _TypeRequired is and it knew
it
was system.bool. But where did it get set???

It's "set" basically as a hard-coded statement in the property
declaration. There's no data storing the value; just a line of code that
always returns the same value.

So the _TypeRequired is really nothing until the "get" which would be during
the assignment here:

Type typeRequired = _TypeRequired;

I assume that what happens when it gets to the this statement is that it
1) does the "get" on the _TypeRequired
2) Takes the returned value (system.boolean, system.string, system.integer
etc) and assignes it to typeRequired

And then when you actually do the assignment of Data, it doesn't really
matter what the type is as the object pointer is now pointing at:

public object Data
{
get { return _objCurrent; }
set
{
if (value != null)
{
_ValidateType(value);
}
_objCurrent = value;
_fChanged = true;
}
}

Since it would be something like:

bool temp;
BoolType boolTypeTemp = new BoolType();
boolTypeTemp.Data = true
temp = (bool)boolTypeTemp;

In the 3rd line, we are putting true into the object _objCurrent and
_objCurrent doesn't really care what it is. It is just an object. Of
course, before we actually assigned it we checked the type with
_ValidateType(value).

So now we have an object _objCurrent that is set to the value of true but
_objCurrent doesn't really know that it is a bool, just that it has a value
of true. Which, if I am not mistaken is just a place on the heap with a -1
one in it and _objCurrent is just a pointer to it. Correct?

And when I return it, I need to cast it to bool since we are just passing
back an object which could be anything.

Also, I assume that a null would be a problem if I tried to pass it back a
null. If I did this, I would have a problem since bool can't be null.
Right?

bool temp;
BoolType boolTypeTemp = new BoolType();
boolTypeTemp.Data = null
temp = (bool)boolTypeTemp;


Because the property is "abstract", it's basically a virtual property, but
without a default implementation (think pure virtual in C++). As a
virtual property, the base class can call it without knowing the concrete
type of the instance, and the override will still be executed and return
the right value.

But the value per se isn't initialized or stored anywhere.
[...]
Just out of curiosity - I was wondering why you underscore _ValidateType
and
_TypeRequired. I understand why you do it for _objCurrent (memory
variable)
and why you use prefix the type (obj - hungarian). But I was wondering
about the other 2.

Actually, you don't understand why I do it for _objCurrent. :)

I am in the habit of using the underscore prefix for non-public members of
classes. That's what you're seeing there. That applies both to
_objCurrent field as well as methods and properties (like _ValidateType
and _TypeRequired).

I guess I didn't understand.

What I typically do is use camel case for my memory variables and Pascal
case for my objects, properties and functions.

Of course, this causes a problem in asp.net if I have a textbox named Name
and memory variable as name - now what do I do with my property. What I
typically do is at this point just change the textbox name to objName.

Not really very clean. I need to think it through better.

Thanks,

Tom
 
T

tshad

Ben Voigt said:
It's a property, not a variable, so it is computed each time it is
referenced by calling the getter. The getter is simply "{ return
typeof(bool); }".
Right.

As Peter suggested, I was confused by the Debugger which apparently did the
get itself or just figured it out. But that it was this statement that
actually set the _TypeRequired variable - doing the get the very first
thing.

Thanks,

Tom
 
P

Peter Duniho

So the _TypeRequired is really nothing until the "get" which would be during
the assignment here:

Type typeRequired = _TypeRequired;

Define "is" and "nothing". :)

_TypeRequired is a property; technically speaking, no property is
anything until you call the getter. On the other hand, you might
consider a property "something" if you know the value it will return.
With that point of view, _TypeRequired is different for each concrete
class, and is "something" the moment you instantiate the class.

But yes...you need to "get" a property before a property can really be
considered to have a value. The value it has is whatever the
property's getter returns at that moment, and more generally speaking,
you only know the value of the property at the instant it returns a
value.

Obviously for many classes and properties, the values are a bit more
resilient than that. But the only thing you can say is _generally_
true about a property is that it will return a value when you ask it to.
I assume that what happens when it gets to the this statement is that it
1) does the "get" on the _TypeRequired
2) Takes the returned value (system.boolean, system.string, system.integer
etc) and assignes it to typeRequired

That's correct. Note that this is exactly how any property works,
except that in this case the return value is hard-coded into the getter
rather than being computed or retrieved from some other variable as is
usually the case.
And then when you actually do the assignment of Data, it doesn't really
matter what the type is as the object pointer is now pointing at:

public object Data
{
get { return _objCurrent; }
set
{
if (value != null)
{
_ValidateType(value);
}
_objCurrent = value;
_fChanged = true;
}
}

I'm not really sure what you mean. An object reference (given the .NET
terminology, I prefer to use the word "reference" over "pointer" in
this situation) points (or rather, refers) to the data structure. It
wouldn't "point" to a specific property.
Since it would be something like:

bool temp;
BoolType boolTypeTemp = new BoolType();
boolTypeTemp.Data = true
temp = (bool)boolTypeTemp;

In the 3rd line, we are putting true into the object _objCurrent and
_objCurrent doesn't really care what it is.

If you're going to use this class or anything like it, you should
probably familiarize yourself with boxing, if you're not already. In
particular, it would be more precise to say that the value "true" is
boxed into an object instance, and the reference to _that_ instance is
what is stored in _objCurrent.
It is just an object. Of
course, before we actually assigned it we checked the type with
_ValidateType(value).

So now we have an object _objCurrent that is set to the value of true but
_objCurrent doesn't really know that it is a bool, just that it has a value
of true.

Well, all that _objCurrent "knows" is that it has a reference to
something that is an Object. It doesn't even know that the object has
a value type boxed inside it, never mind what the actual value of that
value type is.
Which, if I am not mistaken is just a place on the heap with a -1
one in it and _objCurrent is just a pointer to it. Correct?

To be honest, I have no idea. I'm used to a boolean type being stored
as 0 for false and 1 for true, but .NET could use -1 for all I know.

I try to avoid worrying about the internal representation as much as
possible, since the whole point of encapsulating data in higher-level
types is so that you don't care what the internal representation is.
And I haven't yet run into a need to know in .NET for bool, so I can't
actually answer that question. :)

Now, all that said...if one assumes that all that the BitConverter
class does is literally copy the bytes from the source type to a byte
array, and one further assumes that the sample code and output provided
with the GetBytes(bool) doc page is correct, then in .NET a bool is
stored as a 1, just as in other languages.

http://msdn2.microsoft.com/en-us/library/atf689tw.aspx
And when I return it, I need to cast it to bool since we are just passing
back an object which could be anything.

Yes. Thus the convenience property, TypedData, to do the casting for
you in an easier-to-read and easier-to-type way.
Also, I assume that a null would be a problem if I tried to pass it back a
null. If I did this, I would have a problem since bool can't be null.
Right?

Right. Though, you would have this in any context where you try to
copy a nullable version of a value type into a regular, non-nullable
version of a value type (for example, using .NET 2.0's Nullable<T>
generic type).

Basically, when you've stored a value type in a nullable
representation, since value types can't be null, you always have to
check for null before assigning them back. In your class here,
presumably you would use the IsNull property to do that, or of course
you could always just compare the Data property to null.

You wouldn't want to get the TypedData value before checking for null,
or else you'll get an exception casting the value back to bool.
(Though, in some designs it might be that's the behavior you want;
instead of checking for null, just let the exception happen and handle
it as appropriate).

See http://msdn2.microsoft.com/en-us/library/ms173224.aspx for one
technique for dealing with nullable-to-non-nullable assignments.
[...]
What I typically do is use camel case for my memory variables and Pascal
case for my objects, properties and functions.

Of course, this causes a problem in asp.net if I have a textbox named Name
and memory variable as name - now what do I do with my property. What I
typically do is at this point just change the textbox name to objName.

Not really very clean. I need to think it through better.

Well, for what it's worth, I recommend doing what works best for you.
Just because I use Hungarian and prefix non-public members with an
underscore, that doesn't mean it's a useful technique for everyone.

And note that I only use Hungarian for internal stuff. My public
properties follow the Microsoft recommendation for .NET naming, and
while I don't explicitly follow their recommendation for methods, the
Hungarian guidelines for naming methods is effectively a superset of
the .NET recommendations for the most part so there's not really any
difference.

That said, if you're running into naming conflicts with your current
style then, yes...you might want to think about it more. :)

Pete
 
T

tshad

Peter Duniho said:
Define "is" and "nothing". :)

_TypeRequired is a property; technically speaking, no property is anything
until you call the getter. On the other hand, you might consider a
property "something" if you know the value it will return. With that
point of view, _TypeRequired is different for each concrete class, and is
"something" the moment you instantiate the class.

But yes...you need to "get" a property before a property can really be
considered to have a value. The value it has is whatever the property's
getter returns at that moment, and more generally speaking, you only know
the value of the property at the instant it returns a value.
I always looked at a property as a conduit to some value but that it didn't
do anything until you called it (get). So it was confusing that the value
seemed to be "something" before being called by the debugger. But in
actuality, I guess you could say the debugger was doing a "get" to get the
value.
Obviously for many classes and properties, the values are a bit more
resilient than that. But the only thing you can say is _generally_ true
about a property is that it will return a value when you ask it to.


I'm not really sure what you mean. An object reference (given the .NET
terminology, I prefer to use the word "reference" over "pointer" in this
situation) points (or rather, refers) to the data structure. It wouldn't
"point" to a specific property.

What I was saying was that when you do the line "_objCurrent = value;",
value can be anything (bool, int, string, etc). To the class it is just an
object (not a bool, int or string). The statement doesn't care, which is
why you need to do the ValidateType before. The value really gets put on
the heap and _objCurrent is just a pointer to that location. Right?
If you're going to use this class or anything like it, you should probably
familiarize yourself with boxing, if you're not already. In particular,
it would be more precise to say that the value "true" is boxed into an
object instance, and the reference to _that_ instance is what is stored in
_objCurrent.
I only sort of understand boxing.

If I understand it correctly, _objCurrent is just a pointer on the Stack
that points to something on the Heap.

When I assign true to an object, it does
1) a "memalloc" (from the C++ days) and grabs a portion of memory
2) puts the value (true in this case, "This is a test" in the case of a
string) there
3) then puts the pointer (reference) in _objCurrent.
Well, all that _objCurrent "knows" is that it has a reference to something
that is an Object. It doesn't even know that the object has a value type
boxed inside it, never mind what the actual value of that value type is.

What is confusing is that Data is type "object", as you said. How does it
know how much memory to allocate? I assume that the Property knows how much
data is being passed. Obviously, a string would/could take many bytes. We
do the _ValidateType to check the type, but then we just move the value
(which could be any type) to the heap.
To be honest, I have no idea. I'm used to a boolean type being stored as
0 for false and 1 for true, but .NET could use -1 for all I know.
I agree. I am not sure what is put there either (I believe it is 0 for
false and -1 for true but it doesn't matter).
I try to avoid worrying about the internal representation as much as
possible, since the whole point of encapsulating data in higher-level
types is so that you don't care what the internal representation is. And
I haven't yet run into a need to know in .NET for bool, so I can't
actually answer that question. :)

Now, all that said...if one assumes that all that the BitConverter class
does is literally copy the bytes from the source type to a byte array, and
one further assumes that the sample code and output provided with the
GetBytes(bool) doc page is correct, then in .NET a bool is stored as a 1,
just as in other languages.

http://msdn2.microsoft.com/en-us/library/atf689tw.aspx


Yes. Thus the convenience property, TypedData, to do the casting for you
in an easier-to-read and easier-to-type way.


Right. Though, you would have this in any context where you try to copy a
nullable version of a value type into a regular, non-nullable version of a
value type (for example, using .NET 2.0's Nullable<T> generic type).

Basically, when you've stored a value type in a nullable representation,
since value types can't be null, you always have to check for null before
assigning them back. In your class here, presumably you would use the
IsNull property to do that, or of course you could always just compare the
Data property to null.

You wouldn't want to get the TypedData value before checking for null, or
else you'll get an exception casting the value back to bool. (Though, in
some designs it might be that's the behavior you want; instead of checking
for null, just let the exception happen and handle it as appropriate).

See http://msdn2.microsoft.com/en-us/library/ms173224.aspx for one
technique for dealing with nullable-to-non-nullable assignments.

Actually, I do have a Nullhandling class that does just like my last class
that we are working on and I plan on using the same techniques we did here
to make it work. I use it for moving data to and from my database records
and I use these classes to handle the nulls and track changes.

The call to move data from a database to my classes would be something like:

NullHandler.GetValueFromDbObject((object)user["UserID"],ref userID);

where userID is defined as:

private IntType userID = new IntType();

The code for the first part of my NullHandler is:
******************************************
using System;
using System.IO;
using FtsData;

namespace FtsData
{
[Serializable]
public sealed class NullHandler
{
private NullHandler()
{
}

public static void GetValueFromDbObject(object dbObjectValue, ref
StringType destination)
{
if (dbObjectValue == null || dbObjectValue == DBNull.Value)
{
// Set the Null flag
destination.SetNull();
return;
}
destination.Data = Convert.ToString(dbObjectValue);
}

public static void GetValueFromDbObject(object dbObjectValue, ref CharType
destination)
{
if (dbObjectValue == null || dbObjectValue == DBNull.Value)
{
// Set the Null flag
destination.SetNull();
return;
}
destination.Data = Convert.ToChar(dbObjectValue);
}

public static void GetValueFromDbObject(object dbObjectValue, ref BoolType
destination)
{
if (dbObjectValue == null || dbObjectValue == DBNull.Value)
{
// Return the max value.
destination.SetNull();
return;
}

// Check for a string.
string str = dbObjectValue as string;

// If the string is not null, check for empty.
if (str != null)
{
// If the string is empty, return the max value.
if (str == string.Empty)
{
// Set the Null flag
destination.SetNull();
return;
}
}
// Return the object, converted to a decimal.
destination.Data = Convert.ToBoolean(dbObjectValue);
}

******************************************

Since a lot of the data is the same I was looking at whether to do the same
type of thing. I'm not sure if it is worth it or not as it does work as it
is but I may do it just for the practice.
[...]
What I typically do is use camel case for my memory variables and Pascal
case for my objects, properties and functions.

Of course, this causes a problem in asp.net if I have a textbox named
Name
and memory variable as name - now what do I do with my property. What I
typically do is at this point just change the textbox name to objName.

Not really very clean. I need to think it through better.

Well, for what it's worth, I recommend doing what works best for you.
Just because I use Hungarian and prefix non-public members with an
underscore, that doesn't mean it's a useful technique for everyone.

And note that I only use Hungarian for internal stuff. My public
properties follow the Microsoft recommendation for .NET naming, and while
I don't explicitly follow their recommendation for methods, the Hungarian
guidelines for naming methods is effectively a superset of the .NET
recommendations for the most part so there's not really any difference.

That said, if you're running into naming conflicts with your current style
then, yes...you might want to think about it more. :)
True.

Thanks,

Tom
 
P

Peter Duniho

I always looked at a property as a conduit to some value but that it didn't
do anything until you called it (get). So it was confusing that the value
seemed to be "something" before being called by the debugger. But in
actuality, I guess you could say the debugger was doing a "get" to get the
value.

Not only could I say that, I would. :)

That's how properties work. You have to call the getter method to get
the value. Since calling a getter is an instaneous event, rather than
something that's stored somewhere, a property's value is only known at
the time you call the getter.

Some properties never change in value, such as the one we're talking
about here. Others are more conventional, and change in value only
when you call the setter. And still others are changing in value all
the time (at this extreme, see for example DateTime.Now).

The one thing that all properties have in common is that whatever one
might consider the "value" of a property, the only way to know for sure
what the value is at any given moment is to call the getter for the
property. And the instance you call that getter, there are no
fundamental guarantees about what might be returned the next time you
call the getter (though many classes of course provide a guarantee
above and beyond what the language offers).

To me, it's sort of like a little Heisenberg thing going on. You have
to measure the state of the property to know its value. Granted, for
most properties measuring the state doesn't itself necessarily change
the state, but it could and more importantly you still can't say
anything about the future state of the property even having obtained
the state at some instantaneous point in time. :)

What I was saying was that when you do the line "_objCurrent = value;",
value can be anything (bool, int, string, etc). To the class it is just an
object (not a bool, int or string). The statement doesn't care, which is
why you need to do the ValidateType before. The value really gets put on
the heap and _objCurrent is just a pointer to that location. Right?

Basically, yes.
I only sort of understand boxing.

If I understand it correctly, _objCurrent is just a pointer on the Stack
that points to something on the Heap.

Not really. _objCurrent is a field inside a class. All classes are
reference types, which means that all classes are allocated from the
heap. So _objCurrent is a memory location in the heap, that references
something else that's stored in the heap.
When I assign true to an object, it does
1) a "memalloc" (from the C++ days) and grabs a portion of memory
2) puts the value (true in this case, "This is a test" in the case of a
string) there
3) then puts the pointer (reference) in _objCurrent.

That much is basically correct, not counting the hand-waving. :)
There is more to boxing though than just allocating a large enough area
to hold the value itself. It's oversimplifying things to say that just
the value is stored (that is, a boxed int for example is going to take
more space than just the 32 bits for the int).
What is confusing is that Data is type "object", as you said. How does it
know how much memory to allocate?

Because a reference is always just 32 bits. The act of boxing a value
type needs to know how much space to allocate, to contain the value
type along with the class that's containing it. But once the value
type has been boxed (and this occurs _before_ the assignment to the
Data property), it's just a regular reference and always only takes as
much space to store as any reference: 32 bits.

(Ignoring the possibility of a 64-bit .NET for the moment :) )
I assume that the Property knows how much
data is being passed. Obviously, a string would/could take many bytes. We
do the _ValidateType to check the type, but then we just move the value
(which could be any type) to the heap.

Well, a string is even easier, since the String class is already a
reference type. No boxing has to happen; the reference that is already
a reference to the string instance is simply copied to the _objCurrent
field that is the backing store for the Data property.

But again, the property does know how much data is being passed,
because that data is always 32 bits.
[...]
Actually, I do have a Nullhandling class that does just like my last class
that we are working on and I plan on using the same techniques we did here
to make it work. I use it for moving data to and from my database records
and I use these classes to handle the nulls and track changes.

The call to move data from a database to my classes would be something like:

NullHandler.GetValueFromDbObject((object)user["UserID"],ref userID);

where userID is defined as:

private IntType userID = new IntType();

Well, the first thing I notice is that you're using the "ref" keyword
inappropriately. The "userID" variable is already a reference type.
So the parameter is passing a reference. The reference is passed by
value, but it's still a reference and so even without the "ref" any
changes you make to the object in the called method will be reflected
when accessing the instance through "userID".

See Jon Skeet's most excellent article on the topic:
http://www.yoda.arachsys.com/csharp/parameters.html
Since a lot of the data is the same I was looking at whether to do the same
type of thing. I'm not sure if it is worth it or not as it does work as it
is but I may do it just for the practice.

Well, at the very least it does seem like you could consolidate all of
the "check for null, convert to type" code somehow. It sure seems like
all of those GetValueFromDbObject() overloads could be coalesced into a
single method that handles the checking for null.

The way you've written that code, it appears that the caller makes the
determination of type before making the call. So one approach would be
to add a conversion method into your type classes (similar to the
_TypeRequired property, it would be abstract and then implemented by
each concrete type), instantiate the necessary class before calling
GetValueFromDbObject(), and then in that method call the conversion
method to convert from the database object to the necessary C# type for
storage.

I don't know enough about the overall design to know that's the best
way to handle it, but given the code you've posted so far, it's
certainly one way and would at least be better than having all those
overloads. :)

Pete
 
T

tshad

Peter Duniho said:
Not only could I say that, I would. :)

That's how properties work. You have to call the getter method to get the
value. Since calling a getter is an instaneous event, rather than
something that's stored somewhere, a property's value is only known at the
time you call the getter.

Some properties never change in value, such as the one we're talking about
here. Others are more conventional, and change in value only when you
call the setter. And still others are changing in value all the time (at
this extreme, see for example DateTime.Now).

The one thing that all properties have in common is that whatever one
might consider the "value" of a property, the only way to know for sure
what the value is at any given moment is to call the getter for the
property. And the instance you call that getter, there are no fundamental
guarantees about what might be returned the next time you call the getter
(though many classes of course provide a guarantee above and beyond what
the language offers).

To me, it's sort of like a little Heisenberg thing going on. You have to
measure the state of the property to know its value. Granted, for most
properties measuring the state doesn't itself necessarily change the
state, but it could and more importantly you still can't say anything
about the future state of the property even having obtained the state at
some instantaneous point in time. :)



Basically, yes.


Not really. _objCurrent is a field inside a class. All classes are
reference types, which means that all classes are allocated from the heap.
So _objCurrent is a memory location in the heap, that references something
else that's stored in the heap.
I understand that it is a field. But I thought that since the _objCurrent
is an object type that it is just a pointer but not actually an object until
it is assigned to something so it is null.

As far as boxing and the heap go, I assumed it was a pointer to the heap
from articles such as this:

http://www.c-sharpcorner.com/Upload...rticleID=967b4ba5-e4f6-4b80-8e6e-0f4cc23f8e6c

I may not have understood it completely.
That much is basically correct, not counting the hand-waving. :) There
is more to boxing though than just allocating a large enough area to hold
the value itself. It's oversimplifying things to say that just the value
is stored (that is, a boxed int for example is going to take more space
than just the 32 bits for the int).

Really?

Does it have more information about the actual object, such as what type of
object it is?
Because a reference is always just 32 bits. The act of boxing a value
type needs to know how much space to allocate, to contain the value type
along with the class that's containing it. But once the value type has
been boxed (and this occurs _before_ the assignment to the Data property),
it's just a regular reference and always only takes as much space to store
as any reference: 32 bits.

That is what is confusing about boxing.

According to the article above, unless I missed something, boxing actually
moves the data and you are looking at a different piece of data.

For example:

string A = "something"
string B;
B = A

Both A and B are referencing the same location. Such that if I say 'A =
"Something else";', A and B will both be equal to "Something Else".

But if you do
string A = "something";
object B;
B = A;
A = "Something Else"

A and B point to different locations whereas A will be "Something Else" and
B will be "something". Both A and B are pointers in both examples.

Maybe it is different with ints and strings.
(Ignoring the possibility of a 64-bit .NET for the moment :) )
I assume that the Property knows how much
data is being passed. Obviously, a string would/could take many bytes.
We
do the _ValidateType to check the type, but then we just move the value
(which could be any type) to the heap.

Well, a string is even easier, since the String class is already a
reference type. No boxing has to happen; the reference that is already a
reference to the string instance is simply copied to the _objCurrent field
that is the backing store for the Data property.

But again, the property does know how much data is being passed, because
that data is always 32 bits.
[...]
Actually, I do have a Nullhandling class that does just like my last
class
that we are working on and I plan on using the same techniques we did
here
to make it work. I use it for moving data to and from my database
records
and I use these classes to handle the nulls and track changes.

The call to move data from a database to my classes would be something
like:

NullHandler.GetValueFromDbObject((object)user["UserID"],ref userID);

where userID is defined as:

private IntType userID = new IntType();

Well, the first thing I notice is that you're using the "ref" keyword
inappropriately. The "userID" variable is already a reference type. So
the parameter is passing a reference. The reference is passed by value,
but it's still a reference and so even without the "ref" any changes you
make to the object in the called method will be reflected when accessing
the instance through "userID".

That may be the case.

I wrote this a few years ago and it does work. It seems that it didn't work
without the ref keyword. But they have been that I started building this
with a scalar that was not a reference type and I just kept the code the
same.
See Jon Skeet's most excellent article on the topic:
http://www.yoda.arachsys.com/csharp/parameters.html


Well, at the very least it does seem like you could consolidate all of the
"check for null, convert to type" code somehow. It sure seems like all of
those GetValueFromDbObject() overloads could be coalesced into a single
method that handles the checking for null.

That was what I was thinking about doing.
The way you've written that code, it appears that the caller makes the
determination of type before making the call. So one approach would be to
add a conversion method into your type classes (similar to the
_TypeRequired property, it would be abstract and then implemented by each
concrete type), instantiate the necessary class before calling
GetValueFromDbObject(), and then in that method call the conversion method
to convert from the database object to the necessary C# type for storage.

Before I was thinking about rewritting the NullHandler up until last night.
And it was more necessary since, if you remember, the old DataType Classes
had variables that were the type of the class (BoolType class had First as a
boolean, IntType class had First as an int). Now the variables in the class
are objects. So maybe I can now consolidate them into the DataType class.

The whole point of the NullHandler class is to handle data going to and from
a database where the values can be null in the database and not in my c#
code.

When calling to 2 types of calls in my NullHandler:

NullHandler.GetValueFromDbObject((object)user["UserID"],ref userID);

and in my Property where I use both get the data from the DB and Set the
Data to back to the DB

public object DivisionID
{
get
{
object value = null;
return NullHandler.SetDbObjectValueFromValue(divisionID,ref value);
}
set
{
NullHandler.GetValueFromDbObject(value,ref divisionID);
}
}

The code in the NullHandler for my SetDBObjectValueFromValue would look
something like:

public static object SetDbObjectValueFromValue(LongType sourceValue, ref
object dbObjectValue)
{
if(sourceValue.IsNull())
dbObjectValue = DBNull.Value;
else
dbObjectValue = sourceValue.Data;
return dbObjectValue;
}

Most of this was based on the objects fields being of a specific type and in
the new style they are all objects.
I don't know enough about the overall design to know that's the best way
to handle it, but given the code you've posted so far, it's certainly one
way and would at least be better than having all those overloads. :)
Sounds good to me.

Thanks,

Tom
 

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