I was reading a Business Primitives by CodeBetter.com and was toying around with the idea.
Taking his example of Money, how would one implement this in a way that it can be used similarily as regular value types?
What I mean by that is do this:
Money myMoney = 100.00m;
Instead of:
Money myMoney = new Money(100.00m);
I understand how to override all the operators to allow for functionality doing math etc, but I don't know what needs to be overriden to allow what I'm trying to do.
The idea of this is to minimize code changes required when implementing the new type, and to keep the same idea that it is a primitive type, just with a different value type name and business logic functionality.
Ideally I would have inherited Integer/Float/Decimal or whatever required, and override as needed, however obviously that is not available to structures.
You could provide an implicit cast operator from decimal to Money like so:
class Money {
public decimal Amount { get; set; }
public Money(decimal amount) {
Amount = amount;
}
public static implicit operator Money(decimal amount) {
return new Money(amount);
}
}
Usage:
Money money = 100m;
Console.WriteLine(money.Amount);
Now, what is happening here is not that we are overloading the assignment operator; that is not possible in C#. Instead, what we are doing is providing an operator that can implicitly cast a decimal to Money when necessary. Here we are trying to assign the decimal literal 100m to an instance of type Money. Then, behind the scenes, the compiler will invoke the implicit cast operator that we defined and use that to assign the result of the cast to the instance money of Money. If you want to understand the mechanisms of this, read §7.16.1 and §6.1 of the C# 3.0 specification.
Please note that types that model money should be decimal under-the-hood as I have shown above.
Please go through to get more clarity about this
http://www.csharphelp.com/2006/03/c-operator-overloading/
The assignment operator cannot be defined in C#, but for this kind of assignment you can overload the implicit cast operator:
(inside Money class)
public static implicit operator Money(double value)
{
return new Money(value);
}
Note: I recommend using decimal for accurate money calculation
Related
I've developer a custom integral type. Here it is its definition in C#.
public struct PitchClass
{
private readonly int value;
private PitchClass(int value)
{
this.value = CanonicalModulus.Calculate(value, 12);
}
public static implicit operator PitchClass(int value)
{
return new PitchClass(value);
}
public static implicit operator PitchClass(double value)
{
return new PitchClass((int)Math.Round(value));
}
public static implicit operator int(PitchClass pitchClass)
{
return pitchClass.value;
}
}
The PitchClass is an int whose values are in the range [0, 11].
As you can read from the C# code both int and double values can be implicitly converted to PitchClass using a canonical modulus operator:
PitchClass pitchClass = -3;
Console.WriteLine(pitchClass); // 9
The double value is also rounded during implicit conversion:
PitchClass pitchClass = -3.4d;
Console.WriteLine(pitchClass); // 9
I couldn't find other examples of custom data types that do so many things to the data type to convert.
Why? Is it bad practice? If so, is there another way to avoid doing argument validation for every PitchClass variable in every method?
Thanks
It is not bad practice to create a base type and make it convertible to other base data types. Neither is it to define implicit and explicit conversions.
Look at the implementation of Int32 in the .Net Framework. This structure implements many interfaces to make it Convertible to other structure types, to format it nicely and a few other stuff.
If you intend on heavily using this structure, implementing IConvertible, IComparable, IEquatable (and the methods GetHashCode() & Equals()) is a good idea, because almost all the native data types do so.
The Complex type is given as example of Custom data type in the explanation for IConvertible interface and they do many different conversions to and from other types.
Also, the explicit conversion from double to int is doing kind of the same thing you do, making this conversion narrowing (may incur data loss).
I have a class (simplified for the purposes of this question) that wraps a decimal value and uses a couple of implicit operator declarations for converting between the type and the wrapped value:
private class DecimalWrapper
{
public decimal Value { get; private set; }
public DecimalWrapper(decimal value)
{
Value = value;
}
public static implicit operator decimal(DecimalWrapper a)
{
return a != null ? a.Value : default(decimal);
}
public static implicit operator DecimalWrapper(decimal value)
{
return new DecimalWrapper(value);
}
}
The usages of implicit operator here allow things like these to be done:
DecimalWrapper d1 = 5; // uses implicit operator DecimalWrapper
DecimalWrapper d2 = 10;
var result = d1 * d2; // uses implicit operator decimal
Assert.IsTrue(result.Equals(50));
Assert.IsTrue(result == 50);
Now, consider a second class (again, simplified) that has an overloaded constructor that can take a decimal or a DecimalWrapper:
private class Total
{
private readonly DecimalWrapper _total;
public Total(DecimalWrapper total)
{
_total = total;
}
public Total(decimal totalValue)
{
_total = totalValue;
}
}
I would expect to be able to instantiate an instance of Total by passing in an integer value, which would get converted to a decimal:
var total = new Total(5);
However, this results in a compiler error:
The call is ambiguous between the following methods or properties: 'Namespace.Total.Total(TypeTests.DecimalWrapper)' and 'Namespace.Total.Total(decimal)'
To fix this, you have to remove the implicit operator decimal or specify that the value 5 is in fact a decimal:
var total = new Total(5m);
This is all well and good, but I don't see why the implicit operator decimal is relevant here. So, what is going on?
Are you looking for a citation from the language specification?
The cause of this has to do with overload resolution. When you specify an int value as the constructor parameter, no overload is considered "best" because both require a conversion. The specification doesn't consider two levels of conversion different from one level, so the two constructor overloads are equivalent to each other.
As Blorgbeard noted in the comments, you can easily resolve the issue by getting rid of one of the constructors. He suggests removing the DecimalWrapper overload, but since your field is of the DecimalWrapper type, I'd get rid of the decimal overload instead. Doing it this way, if you specify an int value for the constructor, the compiler will implicitly convert to decimal and then DecimalWrapper for you. If you specify a decimal value for the constructor, the compiler will implicity convert to DecimalWrapper for that call, which is what your decimal constructor would have done anyway.
Of course, yet another way to address the issue would be to add other constructors to the Total class, e.g. one that takes an int. Then no conversion is required and the int constructor would be chosen. But this seems like overkill to me.
How can you create a default - non indexer - property in C#?
What I mean by this is I can see that I can create indexer default properties as illustrated on this MSDN page.
This allows me to do things like
Widgets widgets = new Widgets();
Widget result = widgets[1];
But what if I want to achieve something like what Nullable<T> does?
Where you can take
Nullable<decimal> nullDec = 1.23m;
decimal result = nullDec.Value;
OR
decimal result = (decimal)nullDec;
Which I assume is simply a default property implementation to nullDec.Value???
Nullable<T> has special handling in the compiler, but you can do most of that by adding implicit or explicit static conversion operators.
For example, for type Foo you can add an operator:
public static implicit operator string(Foo value)
{
return "abc";
}
public static implicit operator Foo(int value)
{
...
}
allowing:
Foo foo = ..
string s = foo; // uses string(Foo value)
and
int i = 123;
Foo foo = i; // uses Foo(int value)
If you inspect the code of Nullable{T} you will see that the explicit cast implementation is like this:
public static explicit operator T(Nullable<T> value)
{
return &value.Value;
}
So yes you are right.
The way Nullable<T> does it is by providing an explicit conversion operator to T.
So perhaps you are looking for something like:
public static explicit operator Widget(Widgets widgets)
{
// Argument checks here.
return widgets[0];
}
which would let you do:
Widgets widgets = ..
Widget firstWidget = (Widget)widgets;
This does look like a really dodgy and unintuitive API to me so I don't recommend doing this at all. Why not just stick to standard indexers?
Not very sure if I correct understant what you're asking for. Wouldn't be enough to implement cast operators on returning type to achieve what you want?
If it's not what you intend, please explain.
Such kind of features are compiler syntactic sugar (in IL code they all are converted to same low level code), so basically it won't be possible to do this without modifying the C# compiler source.
I know the = operator can't be overloaded, but there must be a way to do what I want here:
I'm just creating classes to represent quantitative units, since I'm doing a bit of physics. Apparently I can't just inherit from a primitive, but I want my classes to behave exactly like primitives -- I just want them typed differently.
So I'd be able to go,
Velocity ms = 0;
ms = 17.4;
ms += 9.8;
etc.
I'm not sure how to do this. I figured I'd just write some classes like so:
class Power
{
private Double Value { get; set; }
//operator overloads for +, -, /, *, =, etc
}
But apparently I can't overload the assignment operator. Is there any way I can get this behavior?
It sounds like you should be using a struct rather than a class... and then creating an implicit conversion operator, as well as various operators for addition etc.
Here's some sample code:
public struct Velocity
{
private readonly double value;
public Velocity(double value)
{
this.value = value;
}
public static implicit operator Velocity(double value)
{
return new Velocity(value);
}
public static Velocity operator +(Velocity first, Velocity second)
{
return new Velocity(first.value + second.value);
}
public static Velocity operator -(Velocity first, Velocity second)
{
return new Velocity(first.value - second.value);
}
// TODO: Overload == and !=, implement IEquatable<T>, override
// Equals(object), GetHashCode and ToStrin
}
class Test
{
static void Main()
{
Velocity ms = 0;
ms = 17.4;
// The statement below will perform a conversion of 9.8 to Velocity,
// then call +(Velocity, Velocity)
ms += 9.8;
}
}
(As a side-note... I don't see how this really represents a velocity, as surely that needs a direction as well as a magnitude.)
You can create implicit conversion operators. There is a page on MSDN with a nice example.
It's also a good idea to make them immutable structs. That's exactly what the "primitives" are, and that's what makes it impossible to inherit from them. You want a struct because you want value-type semantics, instead of reference type semantics. And you want them immutable because mutable value types are generally a bad idea.
I think it cannot be overloaded because C# classes are all derived from Object, so they are basically objects, and when you use the assignment operators, you are basically just referencing another object. On the other hand, if you use a structure, then you basically need all the information, so when you use = operator, all fields will be copied.
So I would say, face it, and implement a function called Copy() and you should be fine :-)
Is there anything wrong with using an implicit operator like the following:
//linqpad c# program example
void Main()
{
var testObject = new MyClass<int>() { Value = 1 };
var add = 10 + testObject; //implicit conversion to int here
add.Dump(); // 11
}
class MyClass<T>
{
public T Value { get; set; }
public static implicit operator T (MyClass<T> myClassToConvert)
{
return myClassToConvert.Value;
}
}
I was thinking I could treat as instance of the object as a value type this way, but seeing as I've never seen an example of this I thought maybe there was a reason not to do something like this that someone could point out?
In my actual code I was thinking of doing this as part of a data abstraction layer, so that I could return objects with information describing the underlying data, but allow the logic code to treat it as a value type when all it needs to know about is the value, and at the same time keep it all nice and type safe with the generics.
If all of the following are true:
all possible values of your MyClass<T> type (including null if it’s not a value type!) map to a valid value of T
the implicit operator never throws (not even for null!)
the implicit conversion makes semantic sense and is not confusing to the client programmer
then there is nothing wrong with this. Of course you could do any of these three things, but it would be bad design. In particular, an implicit operator that throws can be very hard to debug because the place where it is called doesn’t say that it is being called.
For example, consider that T? has no implicit conversion to T (where T is, of course, a value type). If there was such an implicit operator, it would have to throw when the T? is null, as there is no obvious value to convert null to that would make sense for any value type T.
Let me give an example where I had trouble debugging an issue where the implicit operator threw:
public string Foo()
{
return some_condition ? GetSomething() : null;
}
Here, GetSomething returned something of a type I wrote which has a user-defined implicit conversion to string. I made absolutely sure that GetSomething could never return null, and yet I got a NullReferenceException! Why? Because the above code is not equivalent to
return some_condition ? (string)GetSomething() : (string)null;
but to
return (string)(some_condition ? GetSomething() : (Something)null);
Now you can see where the null came from!
That's a great pattern. Just keep in mind that in order to use it as a variable of type T, you have to either explicitly cast it to T, or assign it to a variable of type T. The cast will take place automatically in method calls and other things (such as your addition example) that take a T.
Implicit conversion without assignment?