0

I have a class named FloatPlugIn. I want user to be able to do things like

FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;

float y = 123;
x = y;

That is why I decided to add implicit operator to my class

public static implicit operator FloatPlugIn(float p)
{
    return new FloatPlugIn() { Default = p };
}

Problem is that implicit operator has to be static that is why during conversion new instance of my class is created. As a result I am loosing all the information that was located inside of "old" instance.

Is there a way to fix that? I want float value to be applied to existing instance, not to completely replace it.

walruz
  • 1,135
  • 1
  • 13
  • 33
  • Related: https://stackoverflow.com/questions/4273743/static-implicit-operator. It is a conversion operator which enables conversion implicitly. – Tetsuya Yamamoto Aug 31 '18 at 09:26
  • 3
    You can't "add" with an assignment operator. The C# semantics match what you'd expect to happen if you read this code as an innocent developer, whereas your intent is to subvert them. Why not overload `+` instead? – Jeroen Mostert Aug 31 '18 at 09:27
  • 1
    _I want float value to be added to existing instance..._ Wouldn't an `Add` method be more appropiate then? – Bill Tür stands with Ukraine Aug 31 '18 at 09:27
  • 1
    How about doing `x.Default = y;` ? – Peter B Aug 31 '18 at 09:28
  • 1
    It does sound like you want to set a property on an existing instance. – doctorlove Aug 31 '18 at 09:29
  • Which "old" instance you refer to? The `FloatPlugin`? Casting will usually *create* an entirely new instance (nless you cast into a base-class or an interface). What you want is to *modifiy* an existing one. – MakePeaceGreatAgain Aug 31 '18 at 09:29
  • @HimBromBeere in my code current (old) instance of 'x' variable would be replaced with a new one during the assignment. – walruz Aug 31 '18 at 09:31
  • 1
    Exactly. An *assignment* assigns a **completey independent** instance, so of course you lose all the information of that "old" instance. Thus you don´t want an *assignement*, but a *modification*. – MakePeaceGreatAgain Aug 31 '18 at 09:32
  • @JeroenMostert - He's trying to compose the values, not perform a mathematical addition. The word "added" can mean "composition", not just "addition". – Enigmativity Aug 31 '18 at 09:38
  • @JeroenMostert Thank you, you are right - I changed it from "add" to "apply" to make myself clear – walruz Aug 31 '18 at 09:39
  • @walruz - If you want it applied then it is probably just a property that you need to create. – Enigmativity Aug 31 '18 at 09:42
  • @Enigmativity I just don't see why implicit conversion has to be static. – walruz Aug 31 '18 at 09:47
  • @walruz - I don't think you're understanding what conversion does - it's not casting - it **must** create a new instance. It only makes sense to make it non-static if it were only updating the existing instance. – Enigmativity Aug 31 '18 at 09:50
  • @Enigmativity Thank you, I think you have just answered my question. Please consider re-arranging your last comment as an answer. – walruz Aug 31 '18 at 10:01
  • @walruz - Done. – Enigmativity Aug 31 '18 at 10:12
  • I think the more fundamental problem here is that float is most likely too small to hold a FloatPlugIn's data. – hoodaticus Aug 31 '18 at 19:06

3 Answers3

1

I don't think you're understanding what conversion does - it's not casting - it must create a new instance. It only makes sense to make it non-static if it were only updating the existing instance.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
0

I think it's better in this case if you either use x.Default = y; or if you create a constructor that takes the float like this:

// Constructor
public FloatPlugIn(float p)
{
    Default = p;
}

Usage:

float y = 123;
FloatPlugIn x = new FloatPlugIn(y);
Peter B
  • 22,460
  • 5
  • 32
  • 69
  • Sorry, that is not answering my question. I would rather prefer x.Default = y – walruz Aug 31 '18 at 09:43
  • If you look carefully, you'll see that x.Default = y is the first alternative in my answer :-) – Peter B Aug 31 '18 at 09:55
  • Right :) But I wanted user to be able to treat x variable just like an ordinary float while x still owning some extra information inside. – walruz Aug 31 '18 at 10:05
0

The semantics of the assignment operator requires that behavior. In fact:

The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result. The operands must be of the same type (or the right-hand operand must be implicitly convertible to the type of the left-hand operand).

It is not the purpose of the implicit conversion operator to modify a destination value—note that there may not be any such destination value, such as in case you pass the value to a parameter of a method.

I want float value to be added to existing instance, not to completely replace it.

If you want an addition (in whatever specific sense that would mean in your case), consider overriding the addition + operator, which in turn has effect on the addition assignment += operator. However, you won't eliminate the creation of a new FloatPlugIn instance anyway.

Consider you'd have the following method in FloatPlugIn, which would modify an existing instance:

public void Add(float f)
{
    // do whatever 'addition' means in your case
}

Then the + operator should work like this:

public static FloatPlugIn operator +(FloatPlugIn a, float b)
{
    FloatPlugIn result = a.Clone(); // here Clone() denotes any custom method that creates a copy of that instance
    result.Add(b);
    return b;
}

In your code, the following would work then:

FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;

float y = 123;
x += y; // a new instance is created, but the 'addition' logic is preserved

Also, the same will intuitively work in case of passing a value to a method call:

ProcessMyFloatPlugin(x + 123.0f);

You can see that it is a really good idea to create a new instance of FloatPlugIn as a result of an operator. Otherwise, an in-place modification of x would be, in fact, a nasty side-effect, completely unexpected by any other developer. Note that if performance (avoiding dynamic memory allocations) is a concern, consider using structs.

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
  • 1
    I believe you've misunderstood what the OP meant by "added". He's not suggesting a mathematical addition operation, instead he is asking to somehow compose the float value with the existing instance. – Enigmativity Aug 31 '18 at 09:36
  • 2
    @Enigmativity: the "beauty" of operator overloading (some would call it a curse) is that you're not bound by mathematics. `Foo operator+(Foo foo, float p)` can do basically whatever you want -- it could even return `foo` after modifying it, although that subverts the semantics so bad that you'll likely get into trouble using it. That's not to say a simple, explicit instance method couldn't be the more appropriate solution here -- it depends on what kind of thing `FloatPlugIn` is, and if "adding" floats to it makes sense. – Jeroen Mostert Aug 31 '18 at 09:38
  • @Enigmativity I don't think so. Whatever the OP means by 'addition', be it. The `+` operator just works well to represent an 'addition' in a common sense. See my updated answer that provides a specific example now. If it's clear now, an un-downvote would be welcome then :)) – Ondrej Tucny Aug 31 '18 at 09:40