mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 19:58:49 +00:00
Separate unwrapped Enum.Next/Previous to Unchecked overloads
This commit is contained in:
parent
d9b60fbb94
commit
facc0834f0
61
X10D.Tests/src/Core/EnumTests.cs
Normal file
61
X10D.Tests/src/Core/EnumTests.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace X10D.Tests.Core;
|
||||
|
||||
[TestClass]
|
||||
public class EnumTests
|
||||
{
|
||||
// Microsoft wrongfully decided to have Sunday be 0, Monday be 1, etc.
|
||||
// I personally hate this, Sunday is not the first day of the week.
|
||||
// it's clearly Monday as defined by ISO 8601.
|
||||
// but Microsoft can't fix this without breaking compatibility.
|
||||
// I have feelings...
|
||||
|
||||
[TestMethod]
|
||||
public void Next()
|
||||
{
|
||||
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Sunday.Next());
|
||||
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Monday.Next());
|
||||
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Tuesday.Next());
|
||||
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Wednesday.Next());
|
||||
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Thursday.Next());
|
||||
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Friday.Next());
|
||||
Assert.AreEqual(DayOfWeek.Sunday, DayOfWeek.Saturday.Next()); // Saturday is the "last" day. wrap to "first"
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NextUnchecked()
|
||||
{
|
||||
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Sunday.NextUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Monday.NextUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Tuesday.NextUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Wednesday.NextUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Thursday.NextUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Friday.NextUnchecked());
|
||||
Assert.ThrowsException<IndexOutOfRangeException>(() => DayOfWeek.Saturday.NextUnchecked());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Previous()
|
||||
{
|
||||
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Sunday.Previous()); // Sunday is the "first" day. wrap to "last"
|
||||
Assert.AreEqual(DayOfWeek.Sunday, DayOfWeek.Monday.Previous());
|
||||
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Tuesday.Previous());
|
||||
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Wednesday.Previous());
|
||||
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Thursday.Previous());
|
||||
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Friday.Previous());
|
||||
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Saturday.Previous());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PreviousUnchecked()
|
||||
{
|
||||
Assert.AreEqual(DayOfWeek.Sunday, DayOfWeek.Monday.PreviousUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Tuesday.PreviousUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Wednesday.PreviousUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Thursday.PreviousUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Friday.PreviousUnchecked());
|
||||
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Saturday.PreviousUnchecked());
|
||||
Assert.ThrowsException<IndexOutOfRangeException>(() => DayOfWeek.Sunday.PreviousUnchecked());
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cdoubleextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cendpointextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cenumerableextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cenumextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cfileinfoextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cint16extensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cint32extensions/@EntryIndexedValue">True</s:Boolean>
|
||||
|
@ -6,44 +6,78 @@
|
||||
public static class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the next member defined in a specified enum.
|
||||
/// Returns the value which is defined proceeding this value in the enumeration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="source">The enum value which should be used as the starting point.</param>
|
||||
/// <param name="wrap">
|
||||
/// Optional. <see langword="true" /> if the final value of <typeparamref name="T" /> should wrap around to the first
|
||||
/// value; otherwise, <see langword="false" />. Defaults to <see langword="true" />.
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||
/// <param name="value">The value whose proceeding value to retrieve.</param>
|
||||
/// <returns>
|
||||
/// A value of <typeparamref name="T" /> that is considered to be the next value defined after
|
||||
/// <paramref name="source" />.
|
||||
/// A value of <typeparamref name="T" /> that is considered to be the next value defined after <paramref name="value" />,
|
||||
/// or the first value if <paramref name="value" /> is the final field of the enumeration.
|
||||
/// </returns>
|
||||
public static T Next<T>(this T source, bool wrap = true)
|
||||
public static T Next<T>(this T value)
|
||||
where T : struct, Enum
|
||||
{
|
||||
var array = Enum.GetValues<T>();
|
||||
int index = Array.IndexOf(array, source) + 1;
|
||||
return array.Length == index ? array[wrap ? 0 : index - 1] : array[index];
|
||||
T[] values = Enum.GetValues<T>();
|
||||
int index = Array.IndexOf(values, value) + 1;
|
||||
index %= values.Length;
|
||||
return values[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the previous member defined in a specified enum.
|
||||
/// Returns the value which is defined proceeding this value in the enumeration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="source">The enum value which should be used as the starting point.</param>
|
||||
/// <param name="wrap">
|
||||
/// Optional. <see langword="true" /> if the first value of <typeparamref name="T" /> should wrap around to the final
|
||||
/// value; otherwise, <see langword="false" />. Defaults to <see langword="true" />.
|
||||
/// </param>
|
||||
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||
/// <param name="value">The value whose proceeding value to retrieve.</param>
|
||||
/// <returns>
|
||||
/// A value of <typeparamref name="T" /> that is considered to be the previous value defined before
|
||||
/// <paramref name="source" />.
|
||||
/// A value of <typeparamref name="T" /> that is considered to be the next value defined after
|
||||
/// <paramref name="value" />.
|
||||
/// </returns>
|
||||
public static T Previous<T>(this T source, bool wrap = true)
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="value" /> is the final field of the enumeration.</exception>
|
||||
public static T NextUnchecked<T>(this T value)
|
||||
where T : struct, Enum
|
||||
{
|
||||
var array = Enum.GetValues<T>();
|
||||
int index = Array.IndexOf(array, source) - 1;
|
||||
return index < 0 ? array[wrap ? array.Length - 1 : 0] : array[index];
|
||||
T[] values = Enum.GetValues<T>();
|
||||
int index = Array.IndexOf(values, value) + 1;
|
||||
return values[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value which is defined preceeding this value in the enumeration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||
/// <param name="value">The value whose preceeding value to retrieve.</param>
|
||||
/// <returns>
|
||||
/// A value of <typeparamref name="T" /> that is considered to be the previous value defined after
|
||||
/// <paramref name="value" />, or the last value if <paramref name="value" /> is the first field of the enumeration.
|
||||
/// </returns>
|
||||
public static T Previous<T>(this T value)
|
||||
where T : struct, Enum
|
||||
{
|
||||
T[] values = Enum.GetValues<T>();
|
||||
int index = Array.IndexOf(values, value) - 1;
|
||||
int length = values.Length;
|
||||
|
||||
// negative modulo is not supported in C#. workaround: https://stackoverflow.com/a/1082938/1467293
|
||||
// sure, simply checking for index < 0 is enough, but this expression is so fucking cool!
|
||||
index = (index % length + length) % length;
|
||||
return values[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value which is defined preceeding this value in the enumeration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||
/// <param name="value">The value whose preceeding value to retrieve.</param>
|
||||
/// <returns>
|
||||
/// A value of <typeparamref name="T" /> that is considered to be the previous value defined after
|
||||
/// <paramref name="value" />, or the last value if <paramref name="value" /> is the first field of the enumeration.
|
||||
/// </returns>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="value" /> is the first field of the enumeration.</exception>
|
||||
public static T PreviousUnchecked<T>(this T value)
|
||||
where T : struct, Enum
|
||||
{
|
||||
T[] values = Enum.GetValues<T>();
|
||||
int index = Array.IndexOf(values, value) - 1;
|
||||
return values[index];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user