mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-10 03:05:42 +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_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_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_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_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_005Cint16extensions/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=src_005Cint32extensions/@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
|
public static class EnumExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the next member defined in a specified enum.
|
/// Returns the value which is defined proceeding this value in the enumeration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The enum type.</typeparam>
|
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||||
/// <param name="source">The enum value which should be used as the starting point.</param>
|
/// <param name="value">The value whose proceeding value to retrieve.</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>
|
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// A value of <typeparamref name="T" /> that is considered to be the next value defined after
|
/// A value of <typeparamref name="T" /> that is considered to be the next value defined after <paramref name="value" />,
|
||||||
/// <paramref name="source" />.
|
/// or the first value if <paramref name="value" /> is the final field of the enumeration.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static T Next<T>(this T source, bool wrap = true)
|
public static T Next<T>(this T value)
|
||||||
where T : struct, Enum
|
where T : struct, Enum
|
||||||
{
|
{
|
||||||
var array = Enum.GetValues<T>();
|
T[] values = Enum.GetValues<T>();
|
||||||
int index = Array.IndexOf(array, source) + 1;
|
int index = Array.IndexOf(values, value) + 1;
|
||||||
return array.Length == index ? array[wrap ? 0 : index - 1] : array[index];
|
index %= values.Length;
|
||||||
|
return values[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the previous member defined in a specified enum.
|
/// Returns the value which is defined proceeding this value in the enumeration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The enum type.</typeparam>
|
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||||
/// <param name="source">The enum value which should be used as the starting point.</param>
|
/// <param name="value">The value whose proceeding value to retrieve.</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>
|
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// A value of <typeparamref name="T" /> that is considered to be the previous value defined before
|
/// A value of <typeparamref name="T" /> that is considered to be the next value defined after
|
||||||
/// <paramref name="source" />.
|
/// <paramref name="value" />.
|
||||||
/// </returns>
|
/// </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
|
where T : struct, Enum
|
||||||
{
|
{
|
||||||
var array = Enum.GetValues<T>();
|
T[] values = Enum.GetValues<T>();
|
||||||
int index = Array.IndexOf(array, source) - 1;
|
int index = Array.IndexOf(values, value) + 1;
|
||||||
return index < 0 ? array[wrap ? array.Length - 1 : 0] : array[index];
|
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