Override the property

T

tshad

I have a class that I have that tracks when an object has changed or is set
to null.

I use it for data I get from my database to tell me if I need to update or
reset the data to nulls. I am making changes to it and want to be able to
do the same thing that you can do with nullable types.

If you have int? and you want to change the value you can do:

int? something;

something.value = x;

or

something = x;

You don't have to specify the property.

In my code I do

something.Data = x.

Where the property is set as:

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

This handles the data or nulls.

How can I change this to allow me to call set the variable by either calling
the property or not calling it?

The code itself (with some removed as it is pretty large) is:

**************************************************
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 == DBNull.Value) value = null;
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
protected abstract 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(obj == DBNull.Value)
{
_fChanged = _fChanged;
}
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)
{

Type type = Type.GetType("initial");
Console.WriteLine("Type = {0}",type);
_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(string initial)
{
Type type = initial.GetType();
Console.WriteLine("Type = {0}",type);
_objInitial= initial;
_objCurrent = initial;
}

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

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

Thanks,

Tom
 
A

Anthony Jones

tshad said:
I have a class that I have that tracks when an object has changed or is set
to null.

I use it for data I get from my database to tell me if I need to update or
reset the data to nulls. I am making changes to it and want to be able to
do the same thing that you can do with nullable types.

If you have int? and you want to change the value you can do:

int? something;

something.value = x;

or

something = x;

You don't have to specify the property.

In my code I do

something.Data = x.

Where the property is set as:

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

This handles the data or nulls.

How can I change this to allow me to call set the variable by either
calling the property or not calling it?

The feature you are looking for is the implicit operator. It converts the
type on the RHS to the type of the LHS.
It sounds like you want to be able to assign the value of the Data property
of an existing object without specifying the Data property. This isn't
possible.

Here is what the theoretical implicit operator signature would look like
(using string as the basis for a concrete type) :-

public static implicit operator StringType(string value) { ... }

Note that the return value of the operator method is the type being
converted to, but the signature doesn't take any reference to the value that
might already exist on the LHS, hence you have no way to modify it.

Of course you might be satisfied with this:-

public static implicit operator StringType(string value) { return new
StringType(value); }

This simple returns a new instance of StringType initialised using the value
on the RHS. But is that what you are really after?
 
T

tshad

Anthony Jones said:
The feature you are looking for is the implicit operator. It converts the
type on the RHS to the type of the LHS.
It sounds like you want to be able to assign the value of the Data
property of an existing object without specifying the Data property. This
isn't possible.
What is RHS and LHS?
Here is what the theoretical implicit operator signature would look like
(using string as the basis for a concrete type) :-

public static implicit operator StringType(string value) { ... }

Note that the return value of the operator method is the type being
converted to, but the signature doesn't take any reference to the value
that might already exist on the LHS, hence you have no way to modify it.

Of course you might be satisfied with this:-

public static implicit operator StringType(string value) { return new
StringType(value); }

Might work.

But I am not only concerned with a string type but also a Boolean or Int or
decimal etc.

Really what I want to have happen is to be able to do:

something = "a test";

or

BoolType theBool;
theBool = true;

and have it set:

something.Data = "the test"

or theBool.Data = true

or null if that is passed.

That is what int? does.

May not be possible, but thought that would be neat to be able to do.
This simple returns a new instance of StringType initialised using the
value on the RHS. But is that what you are really after?

Not sure.

Thanks,

Tom
 
F

Family Tree Mike

tshad said:
I have a class that I have that tracks when an object has changed or is set
to null.

I use it for data I get from my database to tell me if I need to update or
reset the data to nulls. I am making changes to it and want to be able to
do the same thing that you can do with nullable types.

If you have int? and you want to change the value you can do:

int? something;

something.value = x;

or

something = x;

You don't have to specify the property.

In my code I do

something.Data = x.

Where the property is set as:

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

This handles the data or nulls.

How can I change this to allow me to call set the variable by either
calling the property or not calling it?

The code itself (with some removed as it is pretty large) is:

**************************************************
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 == DBNull.Value) value = null;
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
protected abstract 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(obj == DBNull.Value)
{
_fChanged = _fChanged;
}
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)
{

Type type = Type.GetType("initial");
Console.WriteLine("Type = {0}",type);
_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(string initial)
{
Type type = initial.GetType();
Console.WriteLine("Type = {0}",type);
_objInitial= initial;
_objCurrent = initial;
}

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

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

Thanks,

Tom


It sounds like you want to indicate that "Data" is the default property for
your class. This is not available to the best of my knowledge in C# (nor VB
either).
 
T

tshad

Family Tree Mike said:
It sounds like you want to indicate that "Data" is the default property
for your class. This is not available to the best of my knowledge in C#
(nor VB either).

I guess that was what I wanted to do.

Since you could do that with the int?, I thought you may be able to a
similar type thing with another object.

Thanks,

Tom

 
A

Anthony Jones

tshad said:
Might work.

But I am not only concerned with a string type but also a Boolean or Int
or decimal etc.

Yes I had grasped that. The above is an example of a method you would add
to your 'StringType' class you included in your code. I thought it fairly
obvious that you would be able to extrapolate how to add a similar method to
your other classes as well.
Really what I want to have happen is to be able to do:

something = "a test";

or

BoolType theBool;
theBool = true;

and have it set:

something.Data = "the test"

or theBool.Data = true

or null if that is passed.

That is what int? does.

No it doesn't. There is a very important difference. int? is short for
Nullable<int>, Nullable<int> as with all other specialisations of
Nullable<T> are structs, IOW are value types. This code:-

int? x;
x = 5;

Fundemantally this code is :-

Nullable<int> x;
x = new Nullable<int>(5);

Note that the value property of the existing content of x is not being
implicitly set, rather a new structure is temporarily created and is content
is copies over the current content of x.
May not be possible, but thought that would be neat to be able to do.

It is possible to do something similar with a Class, a reference type but it
would be illadvised.
Not sure.

Consider this:-

IntType x = new IntType(1);
IntType y = x;
x.Data = 2;

Both x and y point to the same object hence both x.Data and y.Data would
return 2.
Now what if you had an implicit conversion operator method added to IntType
we could now do this:-

x = 3;

However x would now point to different instance of IntType than y. y.Data
would still return 2 and x.Data would return 3.

I really doubt that you would want assignment of this sort to replace the
current object being referenced since it would seem you want to track
whether the value has changed.
 

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