2

此问题中的活动模式在升级到 VS 2012 RTM 后无法编译。它提供了一种进行类型测试并匹配单个模式中的文字的方法。例如:

let (|Value|_|) value = 
  match box value with
  | :? 'T as x -> Some x
  | _ -> None

let getValue (name: string) (r: IDataReader) =
  match r.[name] with
  | null | :? DBNull | Value "" -> Unchecked.defaultof<_>
  | v -> unbox v

这可以在没有活动模式的情况下完成吗?我意识到when可以使用警卫 ( :? string as s when s = "") 但它不能与其他模式结合使用。

4

2 回答 2

1

您应该能够使用参数化的活动模式:

let (|Value|_|) v x = 
    if unbox x = v then 
        Some() 
    else None

用法应该与您现在所拥有的完全一样。

编辑

虽然我不知道重大更改是否是故意的,但我认为通常应该避免使用与输入类型无关的通用返回类型的活动模式。当与类型推断结合使用时,它们可以轻松掩盖细微的错误。考虑以下示例,使用您的原始(|Value|_|)模式:

match [1] with
| Value [_] -> "Singleton"
| _ -> "Huh?"

看起来这不是你真正会尝试的东西——顾名思义,它Value只能与文字一起使用;参数化的活动模式恰好支持这种情况。

于 2012-08-16T15:22:34.130 回答
1

kvb 的变体(它不会做完全相同的事情,因为它假设类型测试成功)可以修改以产生类似的模式:

let (|Value|_|) x value =
  match box value with
  | :? 'T as y when x = y -> Some()
  | _ -> None

但是,存在细微的性能差异。原始的活动模式转换为:

public static FSharpOption<T> |Value|_|<a, T>(a value)
{
    object obj = value;
    if (!LanguagePrimitives.IntrinsicFunctions.TypeTestGeneric<T>(obj))
    {
        return null;
    }
    return FSharpOption<T>.Some((T)((object)obj));
}

也就是说,它会进行类型测试和强制转换。它的用法(match x with Value "" -> ...)转换为:

FSharpOption<string> fSharpOption = MyModule.|Value|_|<object, string>(obj);
if (fSharpOption != null && string.Equals(fSharpOption.Value, ""))
{
    ...
}

最值得注意的是,从模式返回的类型化值使用典型的编译器转换模式匹配(string.Equals用于字符串)。

更新后的模式转换为:

public static FSharpOption<Unit> |Value|_|<T, a>(T x, a value)
{
    object obj = value;
    if (LanguagePrimitives.IntrinsicFunctions.TypeTestGeneric<T>(obj))
    {
        T y = (T)((object)obj);
        T y3 = y;
        if (LanguagePrimitives.HashCompare.GenericEqualityIntrinsic<T>(x, y3))
        {
            T y2 = (T)((object)obj);
            return FSharpOption<Unit>.Some(null);
        }
    }
    return null;
}

它使用泛型相等性并且比匹配文字效率低。用法稍微简单一些,因为模式中包含了相等性:

FSharpOption<Unit> fSharpOption = MyModule.|Value|_|<string, object>("", obj);
if (fSharpOption != null)
{
    ...
}

无论如何,它有效。但我更喜欢原版。

于 2012-08-16T15:45:46.620 回答