How to clone a RectangleF - c#

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.

Related

Constructor of a struct copying a struct

I have a struct which is for an Arc.
I created a constructor that accepts an Arc struct type and i want to basically copy the contents to the new struct i am creating but it seems to zero everything out - not sure if i am misunderstanding how this works.
This is what i have:
//constructor, take an arc - copy it but with a new radius
public Arc(Arc a, float radius)
{
this = a;
a.Radius = radius;
}
With the usage
Arc arc1 = new Arc(arc0, arc0.Radius + _width/2f);
arc1.Draw(Color.green,2);
Arc arc2 = new Arc(arc0, arc0.Radius - _width/2f);
arc2.Draw(Color.green,2);
For some reason arc1 and arc2 have default values for all its fields including the radius field.
I was expecting arc1 and arc2 to basically be copies of arc0 but with a new radius.
Is the use of this not applicable for non reference types or something? I can't see why else i am having this problem.
public Arc(Arc a, float radius)
{
this = a;
a.Radius = radius; // <-- This line is the problem
}
Your use of a.Radius = radius means you're overwriting the .Radius member of parameter a, not field this.a.
Value-types, including struct values in .NET, do not share identity - whereas reference-types (class instances, Object, etc) can do (and do by default). So, with limited exceptions, you can think of each struct-variable as holding its own distinct copy of the entire structure instance.
Change your code to this:
public Arc(Arc source, float radius)
{
this = source; // Copy `source` into `this`
this.Radius = radius; // Then overwrite `this.Radius`
}

C# cast float array to struct of floats

I have a float array in C# that stores data. However, I need to cast the data to structures like Vector2, Vector3 etc. The structures are holding only floats, so there is no data type conversion in the matter of bytes, only in access.
Eg.:
struct Vector3
{
public float x;
public float y;
public float z;
//plus some methods
}
I can copy the whole float array to the struct one manually by creating a new array, but that is kind of slow for big ones. I have tried to do conversion in unsafe code, but using generic is not working and creating special method for every struct I have is kind of "weird".
In C++ I have something like this:
float * arrayFloat = ....
Vector3 * arrayVector3 = reinterpret_cast<Vector3 *>(arrayFloat);
but that is not an option in C#...
Any ideas how to achieve this, or how to change the design?
you could add a constructor to your struct:
struct Vector3
{
public float x;
public float y;
public float z;
public Vector3(float[] vals)
{
if(vals.Length != 3)
throw new ArgumentException();
x = vals[0]; y = vals[1]; z = vals[2];
}
}
...elsewhere
float[] myFloats = { 0.0f, 1.1f, 2.2f };
var myVec = new Vector3(myFloats);
if you're asking if there is something that lets you do this without any work, the answer is no. Any conversion from an array to a struct of your choosing has to be implemented by you, preferably in your struct.
I believe this can work for your struct, using .NET Core 2.1's MemoryMarshal methods.
My answer here describes how. The essence is:
var vectors = MemoryMarshal.Cast<float, Vector3>(floatArray.AsSpan());
var firstVector = vectors[0];
This is C#'s equivalent of a reinterpret cast.
I'm new to C#, and i was struggling with the same problem, what i found useful is to use an enumerator which lazily converts every element on access:
IEnumerator<Vector3> Positions()
{
for (int i = 0; i < _positions.Length / 3; ++i)
{
yield return new Vector3(_positions[3*i],
_positions[3*i+1],
_positions[3*i+2]);
}
}
With this you don't need to copy the whole array and compiler most likely will not create new object of type Vector3 in memory instead it will use registers.

C# Field Reflection not working [duplicate]

I'm trying to write some code that sets a property on a struct (important that it's a property on a struct) and it's failing:
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle();
PropertyInfo propertyInfo = typeof(System.Drawing.Rectangle).GetProperty("Height");
propertyInfo.SetValue(rectangle, 5, null);
The Height value (as reported by the debugger) never gets set to anything - it stays at the default value of 0.
I have done plenty of reflection on classes before and this has worked fine. Also, I know that when dealing with structs, you need to use FieldInfo.SetValueDirect if setting a field, but I don't know of an equivalent for PropertyInfo.
The value of rectangle is being boxed - but then you're losing the boxed value, which is what's being modified. Try this:
Rectangle rectangle = new Rectangle();
PropertyInfo propertyInfo = typeof(Rectangle).GetProperty("Height");
object boxed = rectangle;
propertyInfo.SetValue(boxed, 5, null);
rectangle = (Rectangle) boxed;
Ever heard of SetValueDirect? There's a reason they made it. :)
struct MyStruct { public int Field; }
static class Program
{
static void Main()
{
var s = new MyStruct();
s.GetType().GetField("Field").SetValueDirect(__makeref(s), 5);
System.Console.WriteLine(s.Field); //Prints 5
}
}
There's other methods than the undocumented __makeref which you could use (see System.TypedReference) but they're more painful.

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
}

Casting custom types

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

Categories

Resources