I just upgraded Visual Studio 2022 to .NET7, which includes C# 11. I am interested in trying out the new static abstract interface methods, and so followed the tutorial there.
The article shows how to define Point
and Translation
records that use the new IAdditionOperators<>
interface...
public record Translation<T>(T XOffset, T YOffset) where T : IAdditionOperators<T, T, T>;
public record Point<T>(T X, T Y) where T : IAdditionOperators<T, T, T> {
public static Point<T> operator (Point<T> left, Translation<T> right) =>
left with { X = left.X right.XOffset, Y = left.Y right.YOffset };
}
This enables you to do this...
var pt = new Point<int>(3, 4);
var translate = new Translation<int>(5, 10);
var final = pt translate;
Next it says...
You can make this code more reusable by declaring that these types implement the appropriate arithmetic interfaces. The first change to make is to declare that
Point<T, T>
implements theIAdditionOperators<Point<T>,
Translation, Point>interface. The
Pointtype makes use of different types for operands and the result. The
Point` type already implements an operator with that signature, so adding the interface to the declaration is all you need:
public record Point<T>(T X, T Y) : IAdditionOperators<Point<T>, Translation<T>, Point<T>>
where T : IAdditionOperators<T, T, T>
I'm struggling to understand this bit. Before you add the extra implementation part, you could add a Translation
to a Point
, as shown in the code above, and as explained in the last line of the paragraph I quoted.
Question 1: What have we gained by inserting : IAdditionOperators<Point<T>, Translation<T>, Point<T>>
into the declaration of Point
?
Question 2: In what way does this make the code more reusable? It doesn't seem to enable anything that didn't work before.
After that the article goes on to discuss the additive identity feature, which seems to be a separate point.
Can any explain what I'm missing here? Thanks
CodePudding user response:
For example it allows to define the following generic method and use it with Point<T>
and Translation<T>
(i.e. generically abstract over the addition operations):
public static T AddAll<T, TOther>(T t , List<TOther> c) where T:IAdditionOperators<T, TOther, T>
{
foreach (var item in c)
{
t = t item;
}
return t;
}
And usage (possible due to interface introduction):
Point<int> p = AddAll(new Point<int>(1, 1), new List<Translation<int>>());
CodePudding user response:
Imagine that you create a record that represents a segment (aka two points) that also implements IAdditionOperators<Segment<T>, Translation<T>, Segment<T>>
Then given an array of objects that implements IAdditionOperators<..., Translation<T>, ...>
(a collection of points, a collection of segments or anything that can be translated), one can write a generic method to translate all items using the
operator: hurray!
void Translate<TItem, T>(TItem[] array, Translation<T> translation)
where TItem : IAdditionOperators<TItem, Translation<T>, TItem>
{
foreach (var item in array)
item = item translation;
}