开发者

Overriding Exception.Message / exception pattern matching

I'm trying to pattern match on an exception within its definition. Is something like the following possible using F#'s exception syntax, or must I subclass Exception?

This is what I expected to work:

exception CoordErr of int * int
    with
        override this.Message = 
            let CoordErr(x, y) = this
            sprintf "(%i %i)" x y //ERROR

But yields the errors:

The value or c开发者_如何学运维onstructor 'x' is not defined

The value or constructor 'y' is not defined

EDIT

I also tried adding parens:

let (CoordErr(x, y)) = this

But this gives the error:

This expression was expected to have type exn but here has type CoordErr

UPDATE

The following works, but isn't ideal:

exception CoordErr of int * int
    with
        override this.Message = 
            sprintf "(%i %i)" this.Data0 this.Data1

Is there another way to do this?

UPDATE 2

Taking a cue from kvb's answer, I suppose I could do the following to swallow the incomplete matches warning:

exception CoordErr of int * int
    with
        override this.Message = 
            match this :> exn with
            | CoordErr(x, y) -> sprintf "(%i %i)" x y
            | _ -> Unchecked.defaultof<_>


Your first attempt doesn't work because you're defining a let-bound function called CoordErr which shadows the exception constructor, which isn't what you want.

Your second attempt almost works. Unfortunately, exception definitions don't work quite like discriminated unions: when pattern matching against an exception constructor, the expression that you're matching has to be of type exn (and not of the specific exception subtype). In your case, you are trying to match this (of type CoordErr) against the CoordErr constructor. How's this for a workaround?

exception CoordErr of int * int
    with
        override this.Message = 
          let (CoordErr(x,y)) = upcast this
          sprintf "(%i %i)" x y


Naming the constructor arguments and accessing the corresponding fields seems to work:

exception CoordErr of x : int * y : int
    with
        override this.Message = 
            sprintf "(%i %i)" this.x this.y

I realise this is not a pattern-matching solution, but it does answer the "Overriding Exception.Message" part of your question. :)


You could use the exception aware pattern matching of a try with expression

exception CoordErr of int * int
    with
        override this.Message = 
            try raise this with CoordErr(x, y) -> sprintf "(%i %i)" x y
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜