具有相同别名的 switch 语句中的多个 case
Multiple cases in switch statement with same alias
我想知道是否有意见如何组合我的 switch 的 2 个案例,它们几乎相同,但一个用于可空值,而第二个不是。
switch (rangeA)
{
case Range<int> intRangeA:
{
if (rangeB is Range<int> intRangeB)
{
return intRangeA.ValueFrom <= intRangeB.ValueTo && intRangeA.ValueTo >= intRangeB.ValueFrom;
}
return false;
}
case Range<int?> intRangeA:
{
if (rangeB is Range<int?> intRangeB)
{
return intRangeA.ValueFrom <= intRangeB.ValueTo && intRangeA.ValueTo >= intRangeB.ValueFrom;
}
return false;
}
}
这取决于 rangeA
和 rangeB
的数据类型。
假设他们是 object
,您可以这样做。如果您创建 Range<Something non-comparable>
然后在其上调用 ContainsInclusive
,它将在运行时抛出异常。如果你愿意,你可以为此添加一个额外的检查,但是它变得有点混乱,因为 Nullable<T>
没有实现任何接口,所以你必须求助于反射。
public class Program
{
public static void Main()
{
Foo(new Range<int>() { ValueFrom = 1, ValueTo = 10 }, new Range<int>() { ValueFrom = 0, ValueTo = 10 });
Foo(new Range<int?>() { ValueFrom = 1, ValueTo = 10 }, new Range<int?>() { ValueFrom = 0, ValueTo = 10 });
}
private static bool Foo(object rangeA, object rangeB)
{
return (rangeA, rangeB) switch
{
(Range<int> a, Range<int> b) => b.ContainsInclusive(a),
(Range<int?> a, Range<int?> b) => b.ContainsInclusive(a),
_ => false,
};
}
}
public class Range<T>
{
public T ValueFrom { get; set; }
public T ValueTo { get; set; }
public bool ContainsInclusive(Range<T> other)
{
return Comparer<T>.Default.Compare(other.ValueFrom, this.ValueTo) <= 0 &&
Comparer<T>.Default.Compare(other.ValueTo, this.ValueFrom) >= 0;
}
}
如果您不能以这种方式使用新的 switch 表达式,您可以这样做:
private static bool Foo(object rangeA, object rangeB)
{
return TryContainsInclusive<int>(rangeA, rangeB) ||
TryContainsInclusive<int?>(rangeA, rangeB);
}
private static bool TryContainsInclusive<T>(object a, object b)
{
if (a is Range<T> rangeA && b is Range<T> rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
return false;
}
如果 rangeA
和 rangeB
可以是通用类型,您可以使用更简单的方法:
private static bool Foo<T>(Range<T> rangeA, Range<T> rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
如果 rangeA
和 rangeB
可以是一些基础 Range
类型,那么你可以这样做。同样,如果 T
不可比较,这将在运行时抛出:
public class Program
{
public static void Main()
{
Foo(new Range<int>() { ValueFrom = 1, ValueTo = 10 }, new Range<int>() { ValueFrom = 0, ValueTo = 10 }).Dump();
Foo(new Range<int?>() { ValueFrom = 1, ValueTo = 10 }, new Range<int?>() { ValueFrom = 0, ValueTo = 10 }).Dump();
}
private static bool Foo(Range rangeA, Range rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
}
public abstract class Range
{
public abstract bool ContainsInclusive(Range other);
}
public class Range<T> : Range
{
public T ValueFrom { get; set; }
public T ValueTo { get; set; }
public override bool ContainsInclusive(Range other)
{
if (other is Range<T> o)
{
return Comparer<T>.Default.Compare(o.ValueFrom, this.ValueTo) <= 0 &&
Comparer<T>.Default.Compare(o.ValueTo, this.ValueFrom) >= 0;
}
return false;
}
}
您也可以通过非抽象基础 class Range
来解决问题。 Range<int>
和 Range<int?>
都与此基数 class.
兼容
class Range
{
public object ValueFrom { get; protected set; }
public object ValueTo { get; protected set; }
}
class Range<T> : Range
{
public new T ValueFrom
{
get {
return (T)base.ValueFrom;
}
set {
base.ValueFrom = value;
}
}
public new T ValueTo
{
get {
return (T)base.ValueTo;
}
set {
base.ValueTo = value;
}
}
}
通用 class 的属性隐藏了基础 class 的属性。他们的 setter 受到保护。因此设置值仍然是类型安全的,因为它只能通过泛型 class.
来完成
然后我的解决方案包括测试 From 和 To 值的类型。这也适用于可空类型。如果 nullable
为 null,则 nullable is int i
产生 false
,否则如果我们有 Range<int?>
,它将把 nullable.Value
分配给 i
。
这也允许您将 Range<int>
与 Range<int?>
进行比较。
Range rangeA = new Range<int> { ValueFrom = 5, ValueTo = 12 };
Range rangeB = new Range<int?> { ValueFrom = 10, ValueTo = 18 };
if (rangeA.ValueFrom is int aFrom && rangeA.ValueTo is int aTo &&
rangeB.ValueFrom is int bFrom && rangeB.ValueTo is int bTo) {
return aFrom <= bTo && aTo >= bFrom;
}
return false;
一个可能的改进是在通用变体中有一个强类型的支持变量:
private T _valueFrom;
public new T ValueFrom
{
get {
return _valueFrom;
}
set {
base.ValueFrom = _valueFrom = value;
}
}
至少返回一个值然后在处理通用范围时不涉及拆箱。
我想知道是否有意见如何组合我的 switch 的 2 个案例,它们几乎相同,但一个用于可空值,而第二个不是。
switch (rangeA)
{
case Range<int> intRangeA:
{
if (rangeB is Range<int> intRangeB)
{
return intRangeA.ValueFrom <= intRangeB.ValueTo && intRangeA.ValueTo >= intRangeB.ValueFrom;
}
return false;
}
case Range<int?> intRangeA:
{
if (rangeB is Range<int?> intRangeB)
{
return intRangeA.ValueFrom <= intRangeB.ValueTo && intRangeA.ValueTo >= intRangeB.ValueFrom;
}
return false;
}
}
这取决于 rangeA
和 rangeB
的数据类型。
假设他们是 object
,您可以这样做。如果您创建 Range<Something non-comparable>
然后在其上调用 ContainsInclusive
,它将在运行时抛出异常。如果你愿意,你可以为此添加一个额外的检查,但是它变得有点混乱,因为 Nullable<T>
没有实现任何接口,所以你必须求助于反射。
public class Program
{
public static void Main()
{
Foo(new Range<int>() { ValueFrom = 1, ValueTo = 10 }, new Range<int>() { ValueFrom = 0, ValueTo = 10 });
Foo(new Range<int?>() { ValueFrom = 1, ValueTo = 10 }, new Range<int?>() { ValueFrom = 0, ValueTo = 10 });
}
private static bool Foo(object rangeA, object rangeB)
{
return (rangeA, rangeB) switch
{
(Range<int> a, Range<int> b) => b.ContainsInclusive(a),
(Range<int?> a, Range<int?> b) => b.ContainsInclusive(a),
_ => false,
};
}
}
public class Range<T>
{
public T ValueFrom { get; set; }
public T ValueTo { get; set; }
public bool ContainsInclusive(Range<T> other)
{
return Comparer<T>.Default.Compare(other.ValueFrom, this.ValueTo) <= 0 &&
Comparer<T>.Default.Compare(other.ValueTo, this.ValueFrom) >= 0;
}
}
如果您不能以这种方式使用新的 switch 表达式,您可以这样做:
private static bool Foo(object rangeA, object rangeB)
{
return TryContainsInclusive<int>(rangeA, rangeB) ||
TryContainsInclusive<int?>(rangeA, rangeB);
}
private static bool TryContainsInclusive<T>(object a, object b)
{
if (a is Range<T> rangeA && b is Range<T> rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
return false;
}
如果 rangeA
和 rangeB
可以是通用类型,您可以使用更简单的方法:
private static bool Foo<T>(Range<T> rangeA, Range<T> rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
如果 rangeA
和 rangeB
可以是一些基础 Range
类型,那么你可以这样做。同样,如果 T
不可比较,这将在运行时抛出:
public class Program
{
public static void Main()
{
Foo(new Range<int>() { ValueFrom = 1, ValueTo = 10 }, new Range<int>() { ValueFrom = 0, ValueTo = 10 }).Dump();
Foo(new Range<int?>() { ValueFrom = 1, ValueTo = 10 }, new Range<int?>() { ValueFrom = 0, ValueTo = 10 }).Dump();
}
private static bool Foo(Range rangeA, Range rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
}
public abstract class Range
{
public abstract bool ContainsInclusive(Range other);
}
public class Range<T> : Range
{
public T ValueFrom { get; set; }
public T ValueTo { get; set; }
public override bool ContainsInclusive(Range other)
{
if (other is Range<T> o)
{
return Comparer<T>.Default.Compare(o.ValueFrom, this.ValueTo) <= 0 &&
Comparer<T>.Default.Compare(o.ValueTo, this.ValueFrom) >= 0;
}
return false;
}
}
您也可以通过非抽象基础 class Range
来解决问题。 Range<int>
和 Range<int?>
都与此基数 class.
class Range
{
public object ValueFrom { get; protected set; }
public object ValueTo { get; protected set; }
}
class Range<T> : Range
{
public new T ValueFrom
{
get {
return (T)base.ValueFrom;
}
set {
base.ValueFrom = value;
}
}
public new T ValueTo
{
get {
return (T)base.ValueTo;
}
set {
base.ValueTo = value;
}
}
}
通用 class 的属性隐藏了基础 class 的属性。他们的 setter 受到保护。因此设置值仍然是类型安全的,因为它只能通过泛型 class.
来完成然后我的解决方案包括测试 From 和 To 值的类型。这也适用于可空类型。如果 nullable
为 null,则 nullable is int i
产生 false
,否则如果我们有 Range<int?>
,它将把 nullable.Value
分配给 i
。
这也允许您将 Range<int>
与 Range<int?>
进行比较。
Range rangeA = new Range<int> { ValueFrom = 5, ValueTo = 12 };
Range rangeB = new Range<int?> { ValueFrom = 10, ValueTo = 18 };
if (rangeA.ValueFrom is int aFrom && rangeA.ValueTo is int aTo &&
rangeB.ValueFrom is int bFrom && rangeB.ValueTo is int bTo) {
return aFrom <= bTo && aTo >= bFrom;
}
return false;
一个可能的改进是在通用变体中有一个强类型的支持变量:
private T _valueFrom;
public new T ValueFrom
{
get {
return _valueFrom;
}
set {
base.ValueFrom = _valueFrom = value;
}
}
至少返回一个值然后在处理通用范围时不涉及拆箱。