PC Review


Reply
Thread Tools Rate Thread

Abstract class variables question

 
 
tshad
Guest
Posts: n/a
 
      14th Nov 2007
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


 
Reply With Quote
 
 
 
 
Chris Mullins [MVP - C#]
Guest
Posts: n/a
 
      14th Nov 2007
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...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" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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
>



 
Reply With Quote
 
tshad
Guest
Posts: n/a
 
      14th Nov 2007
"Chris Mullins [MVP - C#]" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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...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" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> 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
>>

>
>



 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      14th Nov 2007
On 2007-11-13 16:46:12 -0800, "tshad" <(E-Mail Removed)> 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.


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

 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      14th Nov 2007
On 2007-11-13 20:00:20 -0800, Peter Duniho <(E-Mail Removed)> said:

> [...]
> 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.

 
Reply With Quote
 
tshad
Guest
Posts: n/a
 
      14th Nov 2007
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


"Peter Duniho" <(E-Mail Removed)> wrote in message
news:2007111320002016807-NpOeStPeAdM@NnOwSlPiAnMkcom...
> On 2007-11-13 16:46:12 -0800, "tshad" <(E-Mail Removed)> 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.

>
> 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
>



 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      14th Nov 2007
On 2007-11-13 22:42:29 -0800, "tshad" <(E-Mail Removed)> said:

> 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

 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      14th Nov 2007
On 2007-11-14 22:16:31 -0800, "tshad" <(E-Mail Removed)> said:

> [...]
> 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

 
Reply With Quote
 
tshad
Guest
Posts: n/a
 
      15th Nov 2007
"Peter Duniho" <(E-Mail Removed)> wrote in message
news:2007111400001816807-NpOeStPeAdM@NnOwSlPiAnMkcom...
> On 2007-11-13 22:42:29 -0800, "tshad" <(E-Mail Removed)> 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


 
Reply With Quote
 
tshad
Guest
Posts: n/a
 
      15th Nov 2007

"Peter Duniho" <(E-Mail Removed)> wrote in message
news:2007111415323916807-NpOeStPeAdM@NnOwSlPiAnMkcom...
> On 2007-11-14 22:16:31 -0800, "tshad" <(E-Mail Removed)> 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
>
> Pete
>



 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Abstract method in non-abstract class Chris Zopers Microsoft ASP .NET 2 8th Aug 2008 12:40 PM
abstract class question about operators t f Microsoft C# .NET 4 27th Jun 2007 12:09 PM
what is abstract class and abstract method N.RATNAKAR Microsoft C# .NET 4 19th Oct 2006 08:23 PM
abstract class question Victor Fees Microsoft C# .NET 2 17th Nov 2003 02:35 AM
RE: Framework 1.1 bug. Derived class generating Abstract base class stubs. Sometimes. MSFT Microsoft VB .NET 3 4th Nov 2003 06:53 AM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 06:25 PM.