Casting custom types - c#

I'm working on a custom struct and I would like to give it the ability to implicitly be created from another type.
Say I have two struct types. Color and ColorX, where Color is a struct already in the framework that I cannot change.
Using implicit operator, to be able to say for example.
Color C;
ColorX CX;
CX = new ColorX();
C = CX;
However, I would like to be able to do it the other way around as well. Either by directly setting it, or by making a cast. Being able to do both would be gold. For example.
C = new Color();
CX = C;
or cast it like so:
CX = (ColorX)C;
Consider all the other useful operators in C#, I'm sure there is a way to do this, I just can't find the syntax.
Any help is greatly appreciated! Thank you very much.

You would do this with the implicit operator in C#:
public static implicit operator ColorX(Color original)
{
return new ColorX(original);
}

You cannot cast two unrelated types to each other.
I would create an extension med
public static class ColorExtensions
{
public static ColorX AsColorX(this Color c)
{
return new ColorC(c);
}
}
to be able to invoke
Color c = new Color();
ColorX cx = c.AsColorX();

Related

Accesing a member directly by the class name

Im trying to create a ufloat class/struct in c#. It's more of a challenge for me, but would help me control some values in code. After trying a couple of approaches, I finally have one that seems to work:
public struct ufloat
{
public float Value
{
get{ return value; }
set
{
if(value < 0)
{
this.value = 0;
}
else
{
this.value = Math.Abs(value);
}
}
}
}
The problem is, I want it to behave like a typical basic type:
ufloat n = 5;
n += 1;
After some thinking I tried to overload the '=' operator, but it is not possible. Now I am out of ideas. This is why I ask, how can you change this:
ufloat x; x.value = 1;
to this:
ufloat x = 0; x = 1;
?
(Sorry if I am losing something really easy, but I am a self-taught "programmer" and I am pretty new to c#. I learnt c++ at first, and going from lower to higher level isn't easy for me.)
You can't overload the = operator, but you can overload the + operator, and then the += operator (which I believe you meant instead of =+) will work in a reasonably obvious way. You'd also need to add an implicit conversion from float to your struct though.
I would strongly advise not making the struct mutable though - instead, let the + operator return a new value. That will make it behave like every other primitive type, and like most other structs. I'd also rename it to USingle to follow the normal .NET naming conventions (where Single is the CLR name for float). You can't add your own C# alias for a name like float is for Single though.
I suspect your type will want:
A constructor accepting a float
Conversions to and from float (note that normally implicit conversions shouldn't throw exceptions - you may want to ignore that, but I'm not sure...)
Overloads for the arithmetic operators (+, -, * and /)
Overrides of ToString, Equals and GetHashCode
Implementation of IComparable<USingle> and IEquatable<USingle>
You should think about what you want to happen if you add two values which are "large positive floats" together - is the intention that your new type is able to support larger positive values than float can, or is it just "float but always non-negative"?
You can not overload = operator but you may write implicit casts, for example this one is for casting an int:
public class ufloat
{
public float value { get; }
public ufloat(int val) { value = Math.Abs(val); }
public static implicit operator ufloat(int input)
{
return new ufloat(input);
}
}
Now if you assign an int value to it, it will implicitly be converted to ufloat:
ufloat x = -5;

Why implicit operator has to be static?

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.
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.
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);
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.

when to use the "new" keyword with structs in c#

I am working with GDI+ and need to create a Brush or Pen. In most cases I should use a "color Struct". Searching around I see two different styles: One is like this:
Brush B1 = new SolidBrush(Color.FromArgb(255, 0, 0));
and the other is:
Color myColor;
myColor = Color.FromArgb(255,0,0);
Brush B2 = new SolidBrush(myColor);
Can anyone describe how can we use a Color without declaring an instance of the Struct with new operator that calls the default constructor.
All that is going on here is that the interesting constructor is non-public, and you must create the value via a static utility method. You can achieve the same thing trivially in your own code:
struct Indirect
{
private readonly int value;
private Indirect(int value)
{
this.value = value;
}
public static Indirect Create(int value)
{
return new Indirect(value);
}
}
struct Direct
{
private readonly int value;
public Direct(int value)
{
this.value = value;
}
}
class Program
{
static void Main()
{
var x = Indirect.Create(42);
var y = new Direct(42);
}
}
Sometimes the expected usage is that the caller uses new; sometimes the expected usage is that the caller gets handed values from a helper method. In the case of Color: the latter. In the case of SolidBrush: the former. Note that this can be the case for both struct and class types - that is not the distinguishing factor.
In the case of Color, there are actually many more fields than you see directly; for example, knownColor, name, state - separately to the ARGB values. Some colors are "known" (from pre-defined named lists); some colors are ad-hoc (from ARGB data). The way you get the color determines these additional values.
The constructors of the type System.Drawing.Color are private and internal, meaning you can't call them from your code.
You'll need to instantiate a color through the given static methods and properties it contains, like Color.FromArgb() or Color.White.
As for the comments, which now make the question clear: those methods and properties are static, which means you don't call them on an instance (new Color().White) but on the type (Color.White).
Judging from its behavior, the method
Color.FromArgb(int red, int green, int blue)
most probably calls
new Color()
in its implementation, i.e. it declares an instance of the struct Color with the new operator.
Both implementations are equal, however
Brush B1 = new SolidBrush(Color.FromArgb(255, 0, 0));
is shorter. I'd rather use even shorter in the case
Brush B1 = new SolidBrush(Color.Red); // R = 255, G = 0, B = 0 is just "Red"
Note, that Brush is IDisposable, that's why it seems that you have put it
using (Brush B1 = new SolidBrush(Color.Red)) {
... // Working with brush
}

How to clone a RectangleF

How do you easily clone (copy) a RectangleF in C#?
There are obviously inelegant ways to do it, such as new RectangleF(r.Location, r.size), but surely there's a .Copy or .Clone method hiding somewhere? But neither of those compiles for me, nor does there appear to be a copy constructor. I suspect there's some simple, C#-standard way of copying any struct, that I just haven't found yet.
In case it matters, my real objective is to make a method that returns an offset version of a rectangle (because, amazingly, RectangleF doesn't have such built in - it has only a mutator method). My best stab at this is:
public static RectangleF Offset(RectangleF r, PointF offset) {
PointF oldLoc = r.Location;
return new RectangleF(new PointF(oldLoc.X+offset.X, oldLoc.Y+offset.Y), r.Size);
}
(Made uglier than it should by be the astounding lack of an addition operator for PointF, but that's another issue.) Is there a simpler way to do this?
RectangleF is a struct i.e. a value type. Consider the following:
public class Program
{
struct S
{
public int i;
}
static void Main(string[] args)
{
S s1 = new S();
S s2 = s1;
s1.i = 5;
Console.WriteLine(s1.i);
Console.WriteLine(s2.i);
}
}
The output is:
5
0
Because S is a struct i.e. s2 is a copy of s1.
A Rect is a struct, a value type.
To clone it just assign it to a new variable.

How to decide what would be returned from an object

Hello I want ot create my own class for Point.
So in some graphic statements I need to call the object of the point to send its X and Y.
I want to know how can I send what I want to that for Example:
myPoint PT = new myPoint(1,2);
myPoint PT2 = new myPoint(10,20);
e.Graphics.DrawLine(pen, PT1, PT2);
I want to return the PT1 and PT2 as regular Point How can I do that?
You can use implicit conversion or explicit conversion. I recommend you explicit conversion.
Add in you myPoint class:
public static explicit operator Point(myPoint myPointToConvert)
{
return new Point(myPointToConvert.???, myPointToConvert.???);
}
With explicit convert you have to specify how you convert it with explicit cast:
e.Graphics.DrawLine(pen, (Point)PT1, (Point)PT2);
It's a little bit longer than in implicit converson but avoid some possible unexpected behavior (because you know exactly what you do).
If you are absolutely sure that you want to do implicit conversion then, in the above operator, just replace explicit by... implicit!

Categories

Resources