views:

2018

answers:

8

Hi everyone

I've got a bit of a problem with a somewhat simple wrapper class I have.

It looks something like this:

public class Wrapper<T>
{
  private T _value;

  public Wrapper<T>(T value)
  {
    _value = value;
  }

  public static implicit operator Wrapper<T>(T value)
  {
    return new Wrapper<T>(value);
  }

  public static implicit operator T(Wrapper<T> value)
  {
    return value._value;
  }
}

I've overriden the implicit converters from and to T, so it behaves almost like an instance of T itself.

e.g.

Wrapper<int> foo = 42;

However I've got a slight problem when assigning one instance of Wrapper to another, since I only want to assign the value of the second Wrapper class.

So right now, I have to do this:

Wrapper<int> foo = 42;
Wrapper<int> bar = (int)foo;

Or expose _value publicly through a property.

However since this is in a library, and I don't want the user to depend on remembering this, do you guys have any idea how I could mimic overridding the assignment operator ?

The problem in just changing the pointer (as it does when assigning a class instance to another), is that I've got a dictionary of pointers to these Wrapper objects, so I cannot have them changing all the time, since the dictionary would stop matching then.

I can see if this is somewhat confusing, so if I've left anything important out, please feel free to ask :-)

+1  A: 

If you look at Nullable<T>...which does a very similar thing to what you are doing here, it exposes the internal value using a .Value property.

The problem in just changing the pointer (as it does when assigning a class instance to another), is that I've got a dictionary of pointers to these Wrapper objects, so I cannot have them changing all the time, since the dictionary would stop matching then.

I'm not sure I follow this, what exactly are you storing in the dictionary? Because if you are storing references, the CLR will update them as necessary.

FlySwat
As I understood it, Nullable<T> was given some additional compiler support to cover these sorts of assignment scenarios.
A J Lane
+3  A: 

You could make Wrapper<T> a struct. However I'm not sure if this would suit your application design or not.

zildjohn01
+2  A: 

Since the assignment operator can't be overloaded, there isn't a real good solution. As somebody else pointed out, using a struct will give you the assignment semantics that you want, but then you're faced with value semantics--often not a good thing.

One option is to overload the constructor:

public Wrapper(Wrapper<T> w)
{
    _value = w._value;
}

Which would result in this syntax:

Wrapper<int> foo = 42;
Wrapper<int> bar = new Wrapper<int>(foo);

Although more verbose than what you have, it reads better.

Or you could add a Clone method (not the ICloneable interface), so that you could write:

Wrapper<int> bar = foo.Clone();

You could get really creative and overload some operator, making it do essentially nothing. I wouldn't recommend that, though. Using operator overloading for those kinds of things typically makes code cryptic and often breaks.

Jim Mischel
A: 

This is what properties are for. They allow you to define what assignment means. You can't define it for a class or struct itself because they are already defined by the language to do necessary things. Just add a Value property to the class.

Alternatively, edit your question to give a broader description of your design and how this Wrapper fits into it, as someone may be able to suggest a simpler approach.

Daniel Earwicker
A: 

Wow thanks alot for all those answers.

I think making the class a struct may solve my issues, I'll have to try that out.

As for the design of the class, it's part of a DB abstraction library built around Reflection.

The wrapper class is actually called DbColumn and used to wrap strings or primitives for matching the database's table (So I have a class per table).

Each table class then contains one or more DbColumns, and I store the reference to each of them in a dictionary, so I don't have to use reflection more than once to fetch them.

It's really a somewhat complex solution, since many "strange" solutions have been used to optimize its performance.

Anyway enough about that, I'll try out using a struct, and see if it works.

I'll let you know how it goes.

A: 

I just looked into it, making the class a struct is really not an option, since it has some logic in the parameterless constructor, plus it inherits an abstract class, which contains internal abstract functions.

I cannot use an interface, as that'd make those functions public, which would break the logic entirely.

I can post the entire class if that'd be helpful, but it's somewhat long (130 lines) Or I could toss up on a seperate server, if that'd be better ? (though it hurts the integrity of this question, as I may delete it eventually from that server)

Also explaining the class is really difficult, without writing a complete essay :-/

Anyway I'll try to illustrate the problem I'm having.

Assume 2 table classes: CustomerTable and UserTable:

public class CustomerTable
{
  Wrapper<string> Name;
}

public class UserTable
{
  Wrapper<string> Name;
}

Now the problem is that some other developer, may use the above code as follows:

CustomerTable customer = new CustomerTable();
UserTable user = new UserTable();
user.Name = customer.Name; // This breaks my internal dictionary

What the developer should had done, in order for it to work, was:

user.Name = (string)customer.Name;

The problem is however, who in their right mind would think about that, when writing code ?

Even if I used a Value property, the developer would still have to remember to write

user.Name = customer.Name.Value; // or user.Name.Value = ....

And again the developer may forget this, and all of a sudden he gets exceptions, or worse: data which isn't persisted to the database.

So my issue is really, that I want the wrapper to be completely transparent (it should be usable as if it was in fact the class/primitive it's wrapping). However when assigning from one wrapper to another, my internal logic breaks.

Phew a lot of writing, and a lot of code - let me know if I overdo the writing.

I'd use the Value property. Implicitly casting a type both ways is never a good idea. Down-stream developers will learn very quickly how to correctly use your library when their naive assignments fail to compile.
A J Lane
A: 

Don't implicitly cast your wrapper both ways.

public class DBValue<T>
{
    public static implicit operator DBValue <T>(T value)
    {
         return new DBValue<T>(value);
    }

    public static explicit operator T(DBValue <T> dbValue)
    {
         return dbValue.Value;
    }

    private readonly T _value;
    public T Value { get { this._value; } }

    public DBValue(T value)
    {
         this._value = value;
    }
}

Casting from DBValue<T> to T is a lossy conversion (as a minimum, you lose the fact that it's a value from the database), and by best-practice should be explicit. If you don't lose anything by casting from DBValue<T> to T, you might as well just use properties that return T.

Basically, you've already seen why you shouldn't be trying to do this: if a DBValue can be substituted for T and the other way around, how does the compiler (or developer) know which one to choose?

Requiring down-stream developers to write:

string value = MyProperty.Value

or

string value = (string)MyProperty

instead of

string value = MyProperty

...isn't all that onerous, and makes sure that everyone knows exactly what's going on.

EDIT:

To actually answer the question, you can't override reference assignment - or make it look like you have - but you shouldn't really need to.

A J Lane
I should note that I've actually made this blunder a couple of times myself - it most particularly caused me problems with numerics: i.e. what is the type of 1 + myValue if myValue is a class that casts as double?
A J Lane
A: 

A J Lane I see what you mean, and I guess you're right - I just wanted to make it as simple as possible to use the library.

The reason for the implicit cast from DbValue to T, is to simply functions which expects T.

for example

literalSomething.Text = Server.HtmlEncode(SomeTable.SomeStringColumn);

rather than

literalSomething.Text = Server.HtmlEncode((string)SomeTable.SomeStringColumn);

This requires the cast to be implicit.

That being said I just read your comment whilst typing this, and I can see that's quite the issue.

I think I'll go back to exposing value through a property, it just requires the developer to type more, and kinda makes the code ugly I think.

Just imagine DbValue:

if (someValue.Value.HasValue) // someValue is DbValue<int?>

But then again it's probably better with "ugly" code, than code which behaves differently from what you'd expect by merely reading it.

I guess this question ends up as a "best practice" question really.

So to conclude, I'll create a Value property and use that instead of implicit casts, and the developer using the library will just have to live with that.

Thanks for your inputs :-)

For more readable (less "ugly") code, you could always assign int? value = someValue.Value; and then proceed as expected.
A J Lane