はじめに
ある変数が範囲内に収まっていれば新しい値を代入する処理などの「範囲を意識した処理」というものはプログラミングをしているを割と良く出てくる課題です。コードを書くと以下のように記述できます。
double value = 10.5;
if (value <= 10 && value >= 0)
{
value = 21.5;
}
こういった判定の繰り返しの記述で毎回コードを書かないように処理を汎用化したいと思います。この処理を各型の「拡張メソッド」として定義して上記判定文を以下のように簡単化します。
value.Assign(21.5, 0, 10);
目次
今回の記事の目次は以下の通りです。
確認環境
- VisualStudio 2019
- .NET Core 3.1 (C#8.0)
- Windows 10
実装した処理一覧
今回実装したメソッドの概要です。
# |
メソッド名 |
説明 |
1 |
Assign(v, min, max) |
変数値が min ~ max の範囲内なら v を代入して true / 範囲外の場合代入せずに false を返す |
2 |
AssignIfOrMore(v, min) |
変数値が min 以上なら v を代入して true / 範囲外の場合代入せずに false を返す |
3 |
AssignIfOrLess(v, max) |
変数値が min 以下なら v を代入して true / 範囲外の場合代入せずに false を返す |
4 |
IsInRange(min, max) |
変数値が min ~ max の範囲内なら true / 範囲外なら false を返す |
5 |
IsInRangeOrMore(min) |
変数値が min 以上 true / 範囲外の場合代入せずに false を返す |
6 |
IsInRangeOrLess(max) |
変数値が min 以下なら true / 範囲外の場合代入せずに false を返す |
7 |
Clamp(min, max) |
変数値が範囲内に収まるように min以下ならmin, max 以上なら max の値を返す |
8 |
ClampSelf(min, max) |
変数値が範囲内に収まるように min以下ならmin, max 以上なら max の値を自分自身に設定する |
上記メソッドのサポートしている型は以下の通りです。(.NETの基本型は全部サポートしました…大変だった、、、
# |
型名 |
サポート状況 |
1 |
byte |
サポート済み |
2 |
sbyte |
サポート済み |
3 |
decimal |
サポート済み |
4 |
double |
サポート済み |
5 |
float |
サポート済み |
6 |
int |
サポート済み |
7 |
uint |
サポート済み |
8 |
long |
サポート済み |
9 |
ulong |
サポート済み |
10 |
short |
サポート済み |
11 |
ushort |
サポート済み |
使い方
前述のメソッドの使い方は以下の通りです。
Assign(v, min, max):現在値が範囲内なら新しい値を代入する
int value_1 = 10;
bool ret_1 = value_1.Assign(30, 0, 10);
int value_2 = 10;
bool ret_2 = value_2.Assign(30, 0, 5);
int value_1 = 10;
bool ret_1 = value_1.AssignIfOrMore(30, 0);
int value_2 = 10;
bool ret_2 = value_2.AssignIfOrMore(30, 20);
AssignIfOrLess(v, max):現在値が min 以下なら値を代入する
int value_1 = 10;
bool ret_1 = value_1.AssignIfOrLess(30, 100);
int value_2 = 10;
bool ret_2 = value_2.AssignIfOrLess(30, 5);
IsInRange(min, max):変数値が min ~ max の範囲内か確認する
int value_1 = 50;
bool ret_1 = value_1.IsInRange(0, 100);
int value_2 = 200;
bool ret_2 = value_2.IsInRange(0, 100);
IsInRangeOrMore(min): 変数値が min 以上か確認する
int value_1 = 100;
bool ret_1 = value_1.IsInRangeOrMore(50);
int value_2 = 100;
bool ret_2 = value_2.IsInRangeOrMore(200);
IsInRangeOrLess(max):変数値が min 以下か確認する
int value_1 = 50;
bool ret_1 = value_1.IsInRangeOrLess(100);
int value_2 = 50;
bool ret_2 = value_2.IsInRangeOrLess(30);
Clamp(min, max):範囲内に収まる値を返す
int value_1 = 100;
int ret_1 = value_1.Clamp(20, 30);
int value_2 = 10;
int ret_2 = value_2.Clamp(20, 30);
ClampSelf(min, max):変数値を範囲内に収める
int value_1 = 100;
value_1.ClampSelf(20, 30);
int value_2 = 10;
value_2.ClampSelf(20, 30);
実装コード
使い方の項目のメソッドを各基本型に拡張メソッドとして実装します。
RangeExtensionクラス
全部のコードがここに入っています。死ぬほど長いので全部コピペしてエディタ上で見たほうがいいかもしれません。
<summary>
</summary>
public static class RangeExtension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref byte self, byte newValue, byte min, byte max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref sbyte self, sbyte newValue, sbyte min, sbyte max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref decimal self, decimal newValue, decimal min, decimal max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref double self, double newValue, double min, double max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref float self, float newValue, float min, float max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref int self, int newValue, int min, int max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref uint self, uint newValue, uint min, uint max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref long self, long newValue, long min, long max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref ulong self, ulong newValue, ulong min, ulong max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref short self, short newValue, short min, short max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Assign(this ref ushort self, ushort newValue, ushort min, ushort max)
{
if (self < min || self > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref byte self, byte newValue, byte min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref sbyte self, sbyte newValue, sbyte min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref decimal self, decimal newValue, decimal min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref double self, double newValue, double min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref float self, float newValue, float min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref int self, int newValue, int min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref uint self, uint newValue, uint min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref long self, long newValue, long min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref ulong self, ulong newValue, ulong min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref short self, short newValue, short min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrMore(this ref ushort self, ushort newValue, ushort min)
{
if (self < min) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref byte self, byte newValue, byte max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref sbyte self, sbyte newValue, sbyte max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref decimal self, decimal newValue, decimal max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref double self, double newValue, double max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref float self, float newValue, float max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref int self, int newValue, int max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref uint self, uint newValue, uint max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref long self, long newValue, long max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref ulong self, ulong newValue, ulong max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref short self, short newValue, short max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool AssignIfOrLess(this ref ushort self, ushort newValue, ushort max)
{
if (newValue > max) return false;
self = newValue;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this byte self, byte min, byte max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this sbyte self, sbyte min, sbyte max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this decimal self, decimal min, decimal max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this double self, double min, double max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this float self, float min, float max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this int self, int min, int max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this uint self, uint min, uint max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this long self, long min, long max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this ulong self, ulong min, ulong max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this short self, short min, short max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(this ushort self, ushort min, ushort max) => max <= self && self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this byte self, byte min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this sbyte self, sbyte min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this decimal self, decimal min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this double self, double min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this float self, float min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this int self, int min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this uint self, uint min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this long self, long min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this ulong self, ulong min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this short self, short min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrMore(this ushort self, ushort min) => self >= min;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this byte self, byte max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this sbyte self, sbyte max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this decimal self, decimal max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this double self, double max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this float self, float max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this int self, int max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this uint self, uint max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this long self, long max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this ulong self, ulong max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this short self, short max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRangeOrLess(this ushort self, ushort max) => max <= self;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte Clamp(this byte self, byte min, byte max)
{
byte value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static sbyte Clamp(this sbyte self, sbyte min, sbyte max)
{
sbyte value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal Clamp(this decimal self, decimal min, decimal max)
{
decimal value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Clamp(this double self, double min, double max)
{
double value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Clamp(this float self, float min, float max)
{
float value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Clamp(this int self, int min, int max)
{
int value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Clamp(this uint self, uint min, uint max)
{
uint value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long Clamp(this long self, long min, long max)
{
long value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Clamp(this ulong self, ulong min, ulong max)
{
ulong value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Clamp(this short self, short min, short max)
{
short value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Clamp(this ushort self, ushort min, ushort max)
{
ushort value = self;
if (self < min) { value = min; }
else if (self > max) { value = max; }
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref byte self, byte min, byte max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref sbyte self, sbyte min, sbyte max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref decimal self, decimal min, decimal max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref double self, double min, double max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref float self, float min, float max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref int self, int min, int max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref uint self, uint min, uint max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref long self, long min, long max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref ulong self, ulong min, ulong max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref short self, short min, short max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ClampSelf(this ref ushort self, ushort min, ushort max)
{
if (self < min) { self = min; }
else if (self > max) { self = max; }
}
}