tags:

views:

135

answers:

6

I want to define a custom exception that has two special properties: Field and FieldValue, and I want the message to be built from those two values in the exception constructor. Unfortunately the Message is read only.

This is what I have, but it still requires the message to be passed.

    public class FieldFormatException: FormatException
    {
        private Fields _field;
        private string _fieldValue;
        public Fields Field{ get{ return _field; } }
        public string FieldValue { get { return _value; } }
        public FieldFormatException() : base() { }
        private FieldFormatException(string message) { }
        public FieldFormatException(string message, Fields field, string value): 
            base(message)
        {
            _fieldValue = value;
            _field = field;               
        }
        public FieldFormatException(string message, Exception inner, Fields field, string value): 
            base(message, inner)
        {
            _fieldValue = value;
            _field = field;
        }
        protected FieldFormatException(System.Runtime.Serialization.SerializationInfo info,
              System.Runtime.Serialization.StreamingContext context): base(info, context){}
    }

How can I remove the Message as a parameter from the constructor, and then set the message based on the value of Field and FieldValue?

+8  A: 

Override it:

    public override string Message
    {
        get
        {
            return string.Format("My message: {0}, {1}", Field, FieldValue);
        }
    }

As discussed in the comments, even though you said that you didn't want a message in the constructor, you may want to consider allowing users to optionally pass their own message to the constructor of your exception and having that displayed as well.

Mark Byers
I knew there was something simple I was not thinking of. Thanks!
Jim McKeeth
You shouldn't do that because it is a standard design guideline to have a message property that the creator of an exception can define (FxCop will complain afaik). Consider overriding ToString instead, or provide an additional constructor that applies a default value to the Message property.
Alex
@Alex: We also know this FxCop warnings. I don't think that every Exception should have all these required constructors. Because of FxCop, we have many Exceptions with constructors which should never be used (eg. because they do not initialize certain fields). So I would suppress these warnings in this cases.
Stefan Steinegger
Personally I prefer the additional constructor over overriding ToString(). The constant "My message" can be replaced with a message that can be taken from the constructor if provided.
Mark Byers
@Steinegger: agree, but if it is possible to comply with the "standard" I would try to do so. In this case: allow setting a custom message.
Alex
+2  A: 

You could override Exception.Message (it's virtual).

Mark Seemann
+7  A: 

Not sure if I understand your question, but what about this?

    public FieldFormatException(Fields field, string value): 
        base(BuildMessage(field, value))
    {
    }

    private static string BuildMessage(Fields field, string value)
    {
       // return the message you want
    }
Stefan Steinegger
I just thought about doing that right after I posted the question. Thanks!
Jim McKeeth
Yeah, that works. The key is making the BuildMessage static and passing the field and value to it.
Jim McKeeth
+2  A: 

You can override the Message property.

Or create a static helper method:

private static string MakeMessage(....) {
  return "Message from parameters of this method";
}

And use that in the base class constructor call:

public FileFormatException(string field, string fieldValue)
  : base(MakeMessage(field, fieldValue) { ... }
Richard
+3  A: 

Can you not just call the base constructor by constructing your message inline? This would leave message out of it entirely.

 public FieldFormatException(string field, string value): 
         base(field.ToString() + value.ToString())
 {
    _fieldValue = value;
    _field = field;               
 }
womp
+1  A: 

I always add a property to my custom exceptions so that I can change the message contents. Actually, I add two properties: one for the message text to be displayed to the user (DisplayMessage), and another for logging many details about the exception (LogMessage) such as user information, the details of a sproc call, data entry details, and so on.

Then, you can leave the Message property alone.

DOK