How to fix CA2225 (OperatorOverloadsHaveNamedAlternates) when using a generic class

I am trying to solve CA2225 , which WARNS on ContrainedValue<T> below, with the following message: Provide a method named 'ToXXX' or 'FromXXX' as an alternate for operator 'ConstrainedValue<T>.implicit operator T(ConstrainedValue<T>)'.

I also inserted PositiveInteger to illustrate a usage example for ConstrainedValue<T> . ConstrainedValue<T> allows derivatives to simply specify the constraint applied to the value type in the constructor. This seems to be a pretty clean way to code this. Is there a way to resolve CA2225 warning, given that I'm dealing with a generic type? How can I provide an alternative operator?

  • Perhaps I could implement ToInt , ToDouble , etc. for all types of values ​​and make them throw, if from than one type? But I think it is bad practice for the ToXXX method to choose?
  • I could create a layer between ConstrainedValue<T> and PositiveInteger<T> , a ConstrainedInteger . I could put ToInt() in this class. But creating a layer just to satisfy CA2225 seems wrong, and I don’t think the warning will disappear on ConstrainedValue<T> , and I would have to suppress this warning.

code:

 namespace OBeautifulCode.AutoFakeItEasy { using System.Diagnostics; using Conditions; /// <summary> /// Represents a constrained value. /// </summary> /// <typeparam name="T">The type of the constrained value.</typeparam> [DebuggerDisplay("{Value}")] public abstract class ConstrainedValue<T> where T : struct { /// <summary> /// Initializes a new instance of the <see cref="ConstrainedValue{T}"/> class. /// </summary> /// <param name="value">The value of the <see cref="ConstrainedValue{T}"/> instance.</param> protected ConstrainedValue(T value) { this.Value = value; } /// <summary> /// Gets the underlying value of the instance. /// </summary> public T Value { get; } /// <summary> /// Performs an implicit conversion from <see cref="ConstrainedValue{T}"/> to the underlying value type. /// </summary> /// <param name="from">The <see cref="ConstrainedValue{T}"/> to convert from.</param> /// <returns> /// The result of the conversion. /// </returns> public static implicit operator T(ConstrainedValue<T> from) { return from.Value; } } /// <summary> /// Represents a positive integer. /// </summary> [DebuggerDisplay("{Value}")] public sealed class PositiveInteger : ConstrainedValue<int> { /// <summary> /// Initializes a new instance of the <see cref="PositiveInteger"/> class. /// </summary> /// <param name="value">The value held by the <see cref="PositiveInteger"/> instance.</param> public PositiveInteger(int value) : base(value) { Condition.Requires(value, nameof(value)).IsGreaterThan(0); } } } 
+6
source share
1 answer

You can make code analysis happy by actually doing what it says:

Paste this into ConstrainedValue<T> and the warning disappears.

 public T ToT() { return this.Value; } 

Personally, I would prefer to suppress the message, you already provide a method to get the value, even if the language does not provide casting.

+3
source

All Articles