Fun with C# 7.1; or "No extension methods for virtual tuples"
Madness? ...yeah, ok, kinda.
So there I was, looking at the release notes for Visual Studio 2017.3, and I saw it: "Implemented C# 7.1". Naturally, I had to try it. This... is a result of that.using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharp7_1.Testing
{
/// <summary>
/// A Vector2 struct with two floating-point values.
/// </summary>
public struct Vector2
{
#region Private Fields
/// <summary>
/// The two floating-point values are stored as "x" and "y" in an
/// anonymous tuple.
/// </summary>
private (float x, float y) values;
#endregion Private Fields
#region Public Constructors
/// <summary>
/// A Vector2 can be constructed out of an appropriate anonymous tuple.
/// </summary>
/// <param name="values"></param>
public Vector2((float x, float y) values)
{
this.values = values;
}
/// <summary>
/// A Vector2 can be constructed out of floating-point x and y values.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public Vector2(float x, float y)
: this((x, y))
{
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// The X-value of the vector.
/// </summary>
public float X { get => values.x; set => values.x = value; }
/// <summary>
/// The Y-value of the vector.
/// </summary>
public float Y { get => values.y; set => values.y = value; }
#endregion Public Properties
#region Public Methods
/// <summary>
/// Implicit deconstruction to an anonymous tuple.
/// </summary>
/// <param name="value"></param>
public static implicit operator (float x, float y) (Vector2 value)
{
return (x: value.X, y: value.Y);
}
/// <summary>
/// Implicit conversion and construction from an an anonymous tuple.
/// </summary>
/// <param name="values"></param>
public static implicit operator Vector2((float x, float y) values)
{
return new Vector2(values);
}
/// <summary>
/// Thanks to our implicit conversions, we can add appropriate
/// anonymous tuples to Vector2s, and vice-versa, and convert back to
/// an anonymous tuple.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static Vector2 operator +(Vector2 left, Vector2 right)
{
return new Vector2(Extensions.Add(left.values, right.values));
}
public static (float x, float y) operator +((float x, float y) left, Vector2 right)
{
return Extensions.Add(left, right.values);
}
/// <summary>
/// Returns the values of the Vector2 as a string.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return values.ToString();
}
#endregion Public Methods
}
public static class Extensions
{
#region Public Methods
/// <summary>
/// Unfortunately (or perhaps "unfortunately"), anonymous tuples do not
/// support extension methods, much less extension operators.
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static (float x, float y) Add((float x, float y) left, (float x, float y) right)
{
return
(
x: left.x + right.x,
y: left.y + right.y
);
}
#endregion Public Methods
}
internal class Program
{
#region Private Methods
private static void Main(string[] args)
{
Console.WriteLine(Extensions.Add((1.5F, 2.5F), (2.0F, 2.5F)));
Vector2 a = (2.5F, 1.5F);
// We don't need to name these "x" and "y", but it helps keep track
// of what they're for.
var b = (x: 2.5F, y: 2.0F);
Console.WriteLine(a + b);
// This! Is! ...A very odd thing to do.
Console.WriteLine((x: 2.5F, y: 1.5F) + (Vector2)(x: 2.5F, y: 2.0F));
Console.ReadKey(true);
}
#endregion Private Methods
}
}
No comments:
Post a Comment