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
精彩评论