When I look at a method in the .NET Framework, it can throw several possible exceptions.
From a planning perspective, what do I need to ask to plan and handle these exceptions? I understand that depending on the impact of an exception, that would influence showing it in the UI layer. For example, if a process at the back end which is opaque to the user experience throws an exception, you would not want to show that to the user as s/he would have no idea what that is.
Thanks
I wanted to write it as a comment but it is to long for the comment textbox...
There are exceptions that are important to show the users because they can handle it by themselves, for example: file name is illegal.
There are exceptions that i find important to show the users because they (the users) will function as my QA team, for example: some method will not update the GUI and they probably will get to the conclusion that they should report that further on, they will show me the exception and i will discover that my array is out of bounds...
there are exceptions that promoting them to the user will just confuse them and like you said
"s/he would have no idea what that is"
for example, For example:
"if a process at the back end which is opaque throws an exception".
those exception i am saving for myself (in database..)..
I am always reminding myself that the end user has a different psychology compare to a developer (-:
I hope i understood your question in the right manner.
You'd normally have a business logic layer in your application, and you'd wrap the methods in that library in safe calls. Those methods may even say what exceptions they can throw, and you may want to handle those exceptions in a unique way if you so wish.
Here's an example of a couple of classes that can handle both unexpected and custom exceptions:
class Program
{
static void Main(string[] args)
{
MethodInvokationResult result = SafeActionInvokator.HandleSafely(() =>
{
MyFakeBusinessEngine.DivideTwoNumbers(5, 0);
});
if (result.Exception is System.DivideByZeroException)
{
Debug.WriteLine($"A divide by zerp exception was caught");
}
else if (!result.Success)
{
Debug.WriteLine($"An unknown error occured.");
}
}
}
^ You can see that you can wrap the calls and handle them in a sensible way.
public class MethodInvokationResult
{
public bool Success { get; set; }
public Exception Exception { get; set; }
}
^ A simple result class
public static class MyFakeBusinessEngine
{
/// <summary>
/// Divides two numbers
/// </summary>
/// <param name="a">numerator</param>
/// <param name="b">denominator</param>
/// <returns>the result</returns>
/// <exception cref="System.DivideByZeroException">When b is zero, divide by zero exception is thrown.</exception>
public static int DivideTwoNumbers(int a, int b)
{
return a / b;
}
}
^ A well documented method, that even tells other developers what exceptions it expects to throw
public static class SafeActionInvokator
{
/// <summary>
/// Executes a method, and if any exception is thrown, will log the error and swallow the exception.
/// </summary>
/// <param name="methodToExecute"></param>
public static MethodInvokationResult HandleSafely(Action methodToExecute)
{
try
{
methodToExecute.Invoke();
return new MethodInvokationResult()
{
Exception = null,
Success = true
};
}
catch (Exception ex)
{
Debug.WriteLine($"{ex}");
return new MethodInvokationResult()
{
Exception = ex,
Success = false
};
}
}
}
^ The wrapper for the method you call, wrapping this in a try catch allows you to handle all exceptions in the same way, or put any custom logic you'd like in there.
This can be expanded to be a call that can return any actual result value too. You could make a generic result class instead of the simple one I've shown.
FINALLY! As to your actual question, I'd create some of these layers throughout your application, and re-throw any exceptions with a severity rating included. These would propagate to your UI layer and you can chose what to do based on Severity.
Maybe even something like this!
public class MajorException : Exception { }
public class MediumException : Exception { }
public class MinorException : Exception { }
public class UserError : Exception { }
Hope this helps!
Is there an alternative to the Notification pattern for multiple messages and success/failure?
I have a class, OperationResult, that I use to return a Success boolean and a list of "error" messages. These messages are sometimes unexpected errors but more often ordinary cases that often happen. Sometimes we return single error messages but other times we return several. I'm hoping to find a better way.
This seems to be more or less the Notification pattern advocated by Fowler. The consumers then do something reasonable with the success state and the errors, most often displaying errors to the user but sometimes continuing on in the case of non-fatal errors.
I thus have lots of service methods (not web service methods) that look something like this:
private ThingRepository _repository;
public OperationResult Update(MyThing thing)
{
var result = new OperationResult() { Success = true };
if (thing.Id == null) {
result.AddError("Could not find ID of the thing update.");
return result;
}
OtherThing original = _repository.GetOtherThing(thing.Id);
if (original == null) return result;
if (AnyPropertyDiffers(thing, original))
{
result.Merge(UpdateThing(thing, original));
}
if (result.Success) result.Merge(UpdateThingChildren(thing));
if (!result.HasChanges) return result;
OperationResult recalcResult = _repository.Recalculate(thing);
if (recalcResult.Success) return result;
result.AddErrors(recalcResult.Errors);
return result;
}
private OperationResult UpdateThing(MyThing ) {...}
private OperationResult UpdateThingChildren(MyThing) {...}
private bool AnyPropertyDiffers(MyThing, OtherThing) {...}
As you can imagine, UpdateThing, UpdateThingChildren, and ThingRepository.Recalculate all have similar OperationResult merging/manipulating code interleaved with their business logic.
Is there an alternative to so much code munging around my returned object? I'd like my code to just focus on the business logic without having to be so particular about manipulating an OperationResult.
I'm hoping to instead have code that looks something like the following, something that better expresses its business logic with less message-handling cruft:
public ??? Update(MyThing thing, ???)
{
if (thing.Id == null) return ???;
OtherThing original = _repository.GetOtherThing(thing.originalId);
if (original == null) return ???;
if (AnyPropertyDiffers(thing, original))
{
UpdateThing(thing, original));
}
UpdateThingChildren(thing);
_repository.Recalculate(thing);
return ???;
}
Any ideas?
Note: throwing exceptions isn't really appropriate here as the messages aren't exceptional.
I think this a situation where functional programming can help, so I'd try with a package porting some F# feautures to C#
using Optional;
and since we want to manage exceptions
using Optional.Unsafe;
At this point we can introduce a helper, to do the typical functional "monad chaining"
public static class Wrap<Tin, Tout>
{
public static Option<Tout, Exception> Chain(Tin input, Func<Tin, Tout> f)
{
try
{
return Option.Some<Tout,Exception>(f(input));
}
catch (Exception exc)
{
return Option.None<Tout, Exception>(exc);
}
}
public static Option<Tout, Exception> TryChain(Option<Tin, Exception> input, Func<Tin, Tout> f)
{
return input.Match(
some: value => Chain(value, f),
none: exc => Option.None<Tout, Exception>(exc)
);
}
}
Now, assuming we have the following updates, that can throw exceptions:
Type2 Update1 (Type1 t)
{
var r = new Type2();
// can throw exceptions
return r;
}
Type3 Update2(Type2 t)
{
var r = new Type3();
// can throw exceptions
return r;
}
Type4 Update3(Type3 t)
{
var r = new Type4();
// can throw exceptions
return r;
}
we'll be able to write a logical flow just following the Happy Path
Option<Type4, Exception> HappyPath(Option<Type1, Exception> t1)
{
var t2 = Wrap<Type1,Type2>.TryChain(t1, Update1);
var t3 = Wrap<Type2, Type3>.TryChain(t2, Update2);
return Wrap<Type3, Type4>.TryChain(t3, Update3);
}
Finally, with an extension class like
public static class Extensions {
public static Option<Type2, Exception> TryChain(this Option<Type1, Exception> input, Func<Type1, Type2> f)
{
return Wrap<Type1, Type2>.TryChain(input, f);
}
public static Option<Type3, Exception> TryChain(this Option<Type2, Exception> input, Func<Type2, Type3> f)
{
return Wrap<Type2, Type3>.TryChain(input, f);
}
public static Option<Type4, Exception> TryChain(this Option<Type3, Exception> input, Func<Type3, Type4> f)
{
return Wrap<Type3, Type4>.TryChain(input, f);
}
}
the Happy Path can be written in a beautiful form
Option<Type4, Exception> HappyPath(Option<Type1, Exception> t1)
{
var t2 = t1.TryChain(Update1);
var t3 = t2.TryChain(Update2);
return t3.TryChain(Update3);
}
I would argue that your service is not doing one thing. Its responsible for validating input and then if validation succeeds updating things. And yes I agree that user needs as many information about errors (violations, name not provided, description to long, date end before date start etc) as you can produce on single request and with that the exceptions are not the way to go.
In my projects I tend to separate concerns of validation and update so the service that does the update has little to none chance of failure. Also I like the strategy pattern to do both validation and update - user requests a change the generic service accepts request of validation/update, calls specific validator/updater which in turn calls generic service to validate/update some dependencies. The generic service will merge results and decide upon success or failure of the operation. The obvious benefit is that violation messages merging is done once in some generic class and specific validator/updater can focus on single entity. On the other hand you might want to validate some database uniqueness or existence of objects on the database this exposes two concerns: extra queries to database (light queries that use Exist to minimize output but its a trip to the database) and the latency between validation and update (in that time database can change and your uniqueness or existence verification can change (this time is relatively small but it can happen). This pattern also minimizes duplication of UpdateThingChildren - when you have simple many to many relation the child can be updated from either one of connected entities.
First, to shortly answer your question, there is no alternative to Notification pattern for combining multiple responses into one. Even if you could throw an exception, you'd have AggregateException which is nothing other than Notification pattern for collecting several exceptions into one (exception is just one kind of output that the method can have).
Notification pattern is a great pattern and I don't see a reason to avoid it actually. Yes, your service layer methods look somewhat chatty, indeed, but those could be refactored. While you have not really asked for the advice how this could be refactored, you need to think about that part mostly.
Couple of advises by looking at your code and in general:
It's normal to make Notification pattern a primary pattern in your codebase if applicable. Not just in the service layer, but everywhere else too. If a method returns more than a primitive value as a result, I don't see how else you would do it. So, every method could return OperationResult{TResult} (generic), which indicates the success/failure, as well as the result of the operation - list of errors if failure, TResult object if success. Every caller method will decide what to do with the result - either discard part or all of it, or return it to its caller up in the call stack.
In your code, you have UpdateThingChildren private method. I'm not sure what that does, but it would be much better expressing the intention if you do thing.UpdateChildren() call on the thing itself.
To decrease the chattiness of your service method, you could use fluent interface-like method chaining. It should not be difficult to implement, assuming that every operation you call returns OperationResult. I'd expect your code to look like this at a minimum:
private ThingRepository _repository;
public OperationResult Update(MyThing thing)
{
return new OperationResult() //removed Success = true, just make that a default value.
.Then(() => thing.ValidateId()) //moved id validation into thing
.Then(() => GetOtherThing(thing.Id)) //GetOtherThing validates original is null or not
.Then(() => thing.AnyPropertyDiffersFrom(original)) //moved AnyPropertyDiffers into thing
.Then(() => thing.UpdateChildren())
.Then(() => _repository.Recalculate(thing));
}
private OperationResult GetOtherThing(MyThing ) {...}
As you can imagine, implementing Then method is not difficult at all. It's defined on OperationResult and takes Func{OperationResult} (generic) as argument. It does not execute func if success == false. Otherwise, it executes func and merges the operation result with itself. At the end, it always returns itself (this).
Some people understand that patterns are not to be broken. But patterns have many critics. And there is really room for improvisation. You still can consider that you have implemented a pattern even if you modified some details. Pattern is general thing and can have specific implementation.
Saying that, you can choose not to go with such fine-grained operation result parsing. I always advocated for something like this pseudo-code
class OperationResult<T>
{
List<T> ResultData {get; set;}
string Error {get; set;}
bool Success {get; set;}
}
class Consumer<T>
{
void Load(id)
{
OperationResult<T> res = _repository.GetSomeData<T>(id);
if (!res.Success)
{
MessageBox.Show(DecorateMsg(res.Error));
return;
}
}
}
As you see, server code return data or error message. Simple. Server code does all the logging, you can write errors to DB, whatever. But I see no value passing complex operation results to consumer. Consumer only needs to know, success or not. Also, if you get multiple things in same operation, what the sense to continue operation if you fail get first thing? May be the problem that you trying to do too many things at once? It is arguable. You can do this
class OperationResult
{
List<type1> ResultData1 {get; set;}
List<type2> ResultData2 {get; set;}
List<type3> ResultData3 {get; set;}
string[] Error {get; set;} // string[3]
bool Success {get; set;}
}
In this case you may fill 2 grids but not third one. And if any errors occur on client side because of this, you will need to handle it with client error handling.
You definitely should feel free to adjust any patterns for your specific needs.
I see two possible options that you could use while avoiding throwing exceptions, but in the end we are only reducing the amount of code needed for messages:
I would refactor the code a little bit in order to make it more standard across all calls. Like the following (See comments inside the parenthesis in the code comments):
public OperationResult Update2(MyThing thing)
{
var original = _repository.GetOtherThing(thing.Id);
if (original == null)
{
return OperationResult.FromError("Invalid or ID not found of the thing update.");
}
var result = new OperationResult() { Success = true };
if (AnyPropertyDiffers(thing, original))
{
result.Merge(UpdateThing(thing, original));
if (!result.HasChanges) return result;
}
result.Merge(UpdateThingChildren(thing));
if (!result.HasChanges) return result;
result.Merge(_repository.Recalculate(thing));
return result;
}
_repository.GetOtherThing - Delegate Id checking to the repository, for simpler code and to ensure we return an error if nothing happened
UpdateThing - With exit after no changes
_repository.Recalculate - We now merge results and return them
Use a scope class shared by all the services at the construction of the services.
// We a scope class shared by all services,
// we don't need to create a result or decide what result to use.
// It is more whether it worked or didn't
public void UpdateWithScope(MyThing thing)
{
var original = _repository.GetOtherThing(thing.Id);
if (_workScope.HasErrors) return;
if (original == null)
{
_workScope.AddError("Invalid or ID not found of the thing update.");
return;
}
if (AnyPropertyDiffers(thing, original))
{
UpdateThing(thing, original);
if (_workScope.HasErrors) return;
}
UpdateThingChildren(thing);
if (_workScope.HasErrors) return;
_repository.Recalculate(thing);
}
_repository.GetOtherThing must add any errors to the _workScope
UpdateThing must add any errors to the _workScope
UpdateThingChildren must add any errors to the _workScope
_repository.Recalculate must add any errors to the _workScope
In this last example we don't need to return anything since the caller will have to verify if the scope is still valid.
Now if there are multiple validations to be performed I would suggest doing another class like Rafal mentioned.
Last note: I would throw exceptions for anything that should be handled in the GUI like the 'thing.Id' sent without a value or not sent at all, that sounds to me like whoever did the interface didn't handle this scenario properly or the current interface is old or unsupported, which normally is enough reason to throw an exception.
You can use exceptions internally without throwing them to callers. This allows you to break out of a failed operation easily, and groups your business logic all in one place. There is still some 'cruft', but it's separated (and could be in its own class) from the business logic, which is contained in the *Internal implementations. Not saying this is the best or only way of approaching this problem, but I may go with this:
public class OperationResult
{
public bool Success { get; set; }
public List<string> Errors { get; set; } = new List<string>();
}
public class Thing { public string Id { get; set; } }
public class OperationException : Exception
{
public OperationException(string error = null)
{
if (error != null)
Errors.Add(error);
}
public List<string> Errors { get; set; } = new List<string>();
}
public class Operation
{
public OperationResult Update(Thing thing)
{
var result = new OperationResult { Success = true };
try
{
UpdateInternal(thing);
}
catch(OperationException e)
{
result.Success = false;
result.Errors = e.Errors;
}
return result;
}
private void UpdateInternal(Thing thing)
{
if (thing.Id == null)
throw new OperationException("Could not find ID of the thing update.");
var original = _repository.GetOtherThing(thing.Id);
if (original == null)
return;
if (AnyPropertyDiffers(thing, original))
result.Merge(UpdateThing(thing, original));
result.Merge(UpdateThingChildren(thing));
if (result.HasChanges)
_repository.Recalculate(thing);
}
}
I would approach with State pattern and internal collection to save information. You can start applying events that change the state and store the information related to the applied event. Finally call get information to wrap them inside operationresult.
A pseudo code
public OperationResult Update(MyThing thing)
{
return new OperationResult
{
Errors = thing.ApplyEvent(Event.NullCheck)
.ApplyEvent(Event.OriginalNullCheck)
.ApplyEvent(Event.OriginalPropertyDiffersCheck)
.CollectInfo(),
Success = true
};
}
public class MyThing
{
private List<string> _errors = new List<string>();
private MyThing _original;
public MyThingState ThingState {get;set;}
public MyThing ApplyEvent(Event eventInfo)
{
MyThingState.ApplyEvent(this, eventInfo)
}
}
public class NullState : MyThingState
{
public MyThing ApplyEvent(MyThing myThing, Event eventInfo)
{
if(mything == null)
{
// use null object pattern
mything.AddErrors("Null value")
// Based on the event, you select which state to instantiate
// and inject dependencies
mything.State = new OriginalNullState();
}
}
}
public class OriginalNullState : MyThingState
{
public void ApplyEvent(MyThing myThing, Event eventInfo)
{
// Get original from database or repository
// Save and validate null
// Store relevant information in _errors;
// Change state
}
}
Even though I would have loved throwing exception, here it is not appropriate because you are not in fail-fast. You are taking corrective measures on non fatal cases. You just want higher layers to know about it.
public OperationResult<DataSet> Update(MyThing thing, OperationResult<DataSet> papa)
{
// Either you have a result object from enclosing block or you have null.
var result = OperationResult<DataSet>.Create(papa);
if (thing.Id == null) return result.Fail("id is null");
OtherThing original = _repository.GetOtherThing(thing.originalId);
if (original == null) return result.warn("Item already deleted");
if (AnyPropertyDiffers(thing, original))
{
UpdateThing(thing, original, result));
// Inside UpdateThing, take result in papa and do this dance once:
// var result = OperationResult<DataSet>.Create(papa);
}
UpdateThingChildren(thing, result);
// same dance. This adds one line per method of overhead. Eliminates Merge thingy
_repository.Recalculate(thing, result);
return result.ok();
}
You can eliminate passing result everywhere using Scope pattern from #BigShot, but i personally do not like ambient contexts. The could be anything you may need to return back.
class OperationResult<T> {
enum SuccessLevel { OK, WARN, FAIL }
private SuccessLevel _level = SuccessLevel.OK;
private List<String> _msgs = new ...
public T value {get; set};
public static OperationResult<T> Create(OperationResult<T> papa) {
return papa==null ? new OperationResult<T>() : papa;
}
public OperationResult<T> Fail(string msg) {
_level = SuccessLevel.Fail;
_msgs.add(msg);
return this; // this return self trick will help in reducing many extra lines in main code.
}
// similarly do for Ok() and Warn()
}
I need to use the value of a variable initialized inside a try block. I have this basic code
Customer customer = null;
try
{
customer = new Customer(....);
}
catch (Exception){}
string customerCode = customer.Code;
If there is no exception, the customer is perfecly usable, but if there is an exception, customer is not initialized, it returns null
I have checked that customer ALLWAYS initializes correctly INSIDE the block. INSIDE It is perfectly usable even in case of exception. But I need it for later use.
Any way to ALLWAYS keep the customer? :)
EDIT:
As you supposed, this was pseudocode. As I can read, it looks like to use exceptions in constructors is a BAD idea. This is part of my REAL code for my constructor.
public class DirectDebitRemmitanceReject
{
int numberOfTransactions;
decimal controlSum;
List<DirectDebitTransactionReject> directDebitTransactionRejects;
public DirectDebitRemmitanceReject(
int numberOfTransactions,
decimal controlSum,
List<DirectDebitTransactionReject> directDebitTransactionRejects)
{
this.numberOfTransactions = numberOfTransactions;
this.controlSum = controlSum;
this.directDebitTransactionRejects = directDebitTransactionRejects;
if (TheProvidedNumberOfTransactionsIsWrong()) ChangeNumberOfTransactionsAndRiseException();
if (TheProvidedControlSumIsWrong()) ChangeControlSumAndRiseException();
}
private bool TheProvidedNumberOfTransactionsIsWrong()
{
return (numberOfTransactions != directDebitTransactionRejects.Count)
}
private bool TheProvidedControlSumIsWrong()
{
return (controlSum !=directDebitTransactionRejects.Select(ddRemmitanceReject => ddRemmitanceReject.Amount).Sum();)
}
private void ChangeNumberOfTransactionsAndRiseException()
{
......
......
throw new ArgumentException(exceptionMessage, "numberOfTransactions")
private void ChangeControlSumAndRiseException()
{
......
......
throw new ArgumentException(exceptionMessage, "controlSum")
}
}
In the methods 'TheProvided...' I check if the arguments are congruent with the sum of values in the list. If not, I update them and inform by raising an ArgumentException
The fact is that I wanted the constructor ALLWAYS returns a valid (congruent) DirectDebitRemmitanceReject, but desired the same constructor to rise the exception if provided wrong numberOfTransactions or controlSum. NumberOfTransactions and controlSum should not be modified later, only readed.
In my tests, this works well
[TestMethod]
[ExpectedException(typeof(System.ArgumentException))]
public void IfTheProvidedControlSumInARemmitanceRejectIsWorgAnExceptionIsThrown()
{
try
{
DirectDebitRemmitanceReject directDebitRemmitanceReject = new DirectDebitRemmitanceReject(
originalDirectDebitRemmitance1MessageID,
2,
100,
directDebitTransactionRejectsList1);
}
catch (System.ArgumentException e)
{
Assert.AreEqual("controlSum", e.ParamName);
Assert.AreEqual("The Control Sum is wrong. Provided: 100. Expected: 150. Initialized with expected value", e.GetMessageWithoutParamName());
throw;
}
}
[TestMethod]
public void IfTheProvidedControlSumInARemmitanceRejectIsWorgItIsCorrected()
{
try
{
DirectDebitRemmitanceReject directDebitRemmitanceReject = new DirectDebitRemmitanceReject(
originalDirectDebitRemmitance1MessageID,
2,
100,
directDebitTransactionRejectsList1);
Assert.AreEqual(150, directDebitRemmitanceReject.ControlSum);
}
catch (ArgumentException) { }
}
But i can,t Assert the directDebitRemmitanceReject.ControlSum outside the 'try' block
So... do I try another aproach (remove the exception from inside the constructor) or is there another workaround?
Thanks! :)
(Sorry for the EXTENSIVE edit) :(
Your example is a perfect illustration of why writing
catch (Exception){}
is a very bad practice.
When you catch an exception, you are supposed to do something about it. If you do not know what to do with an exception in a particular method of your code, don't catch the exception in that method.
If you always need a customer, even when its retrieval causes an exception, add some code to the catch block to set customer variable to some default object:
try {
...
} catch (Exception) {
customer = Customer.Unknown;
}
This assumes that Customer has a property Unknown of type Customer with some default behavior.
Comment: Needed to warn the upper level of my code. Just, when I create an instance, create it, but warn the arguments where wrong. Could you recommend me some better approach?
Make a factory for validating users while creating them:
class CustomerCreationResult {
public Customer Customer() { get; set; }
public CustomerCreationError Error() { get; set; }
}
class CustomerFactory {
public CustomerCreationResult CreateCustomer(String name, int age) { ... }
}
Now you can create your customers as follows:
var r = myCustomerFactory.CreateCustomer(name, age);
if (r.getError() != null) {
... // Present the error
}
Customer customer = r.Customer;
...
If customer always initializes correctly, then why do you have it in the try block?
If you want to persist it when an exception occurs, either move the initialization of customer outside of the try block or use try/catch for smaller chunks of code.
for example:
Customer customer = null;
try
{
//in this block do the stuff that is unlikely to cause exceptions
customer = new Customer(...);
try
{
//stuff that is likely to cause exceptions
}
catch(Exception e)
{
//handle likely errors
}
catch (Exception e)
{
//handle the unusual errors
}
I think 'dasblinkenlight's answer is very good, but for the simplest purpose an if would be enough:
string customerCode = "";
if (customer!=null)
{
customerCode = customer.Code;
}
And you really should check the exception...
I want to learn more about c#, and I've heard that you should use Private specifier and use get/set to make it public.
I got a small application that take textbox data and writes it to a file. And it encrypts the file.
But I can't graps the concept about getters and setters. Here is my one of my classes and Methods that writes to a file.
class MyClass
{
public static bool WriteToFile(string text)
{
string FileName = "C:\\crypt\\crypt.txt";
try
{
using (System.IO.StreamWriter WriteToFile = new System.IO.StreamWriter(FileName))
{
WriteToFile.Write(text);
WriteToFile.Close();
}
return true;
}
catch
{
return false;
}
}
But instead i want to use a property. How should i do it?
This is how i pass in the textbox-data from my main class.
public void button1_Click(object sender, EventArgs e)
{
MyClass c = new MyClass();
if (MyClass.WriteToFile(textBox1.Text))
MessageBox.Show("success, managed to write to the file");
else
MessageBox.Show("Error, Could not write to file. Please check....");
I've looked at various tutorials such as https://channel9.msdn.com/series/C-Fundamentals-for-Absolute-Beginners/15 and tutorials, but I really stuggling.
WriteToFile is a method.
Methods are methods, and properties are properties.
Methods encapsulate behaviour, while properties encapsulate state.
WriteToFile should not be a property, because it does not encapsulate state. In fact, it attempts to write into the file system.
An example of a property would be:
public class MyClass
{
private bool _canWrite;
/// Checks whether the file can be written into the file system
public bool CanWrite
{
get { return _canWrite; }
}
}
From another class, you would call it like this:
if(myClass.CanWrite)
{
// ...
}
Notice that CanWrite does not define any behaviour, it just defines a getter for the _canWrite field, this ensures that external classes don't get to see too much about your class.
Also notice that I define a getter only, this prevents others from setting your property.
There is not much to change to your design besides one little thing. But first things first:
Could you place that code into a property? Sure. Should you? Not at all. Your method WriteToFile is actually doing sth. and thats what methods are for. Properties on the other hand are used for modifying/storing data.
Thats why property-names sound more like Names while method-names generally sound like Commands:
Example
public class Sample
{
private string someText;
// This Property Stores or modifies SomeText
public string SomeText
{
get { return this.someText; }
set { this.someText = value; }
}
// Method that does sth. (writes sometext to a given File)
public void WriteSomeTextToFile(string File)
{
// ...
}
}
Why properties/modifiers?
it is considered good pratice to encapsulate data within propeties like in the example above. A small improvement could be the use of an AutoProperty like so:
public string SomeText { get; set; }
which basically results in the same structure as the combination of an encapsulated field like in the first example.
Why?: because this makes it easy to switch it out or to add logic to your get/set-operations.
For example, you could add validation:
public string SomeText
{
// ...
set
{
if (value.Length > 100)
throw new Exception("The given text is to long!");
this.someText = value;
}
}
SideNote: Possible improvement to your class
The only improvement I could think of is not to swallow the exception in your write method:
public void WriteToFile()
{
using (var fileWriter= new System.IO.StreamWriter(FileName))
{
fileWriter.Write(_text);
fileWriter.Close();
}
}
This is much cleaner and you would not have to "decision" cascades handling the same issue (your try/catch and if/else) are practically doing the same.
public void button1_Click(object sender, EventArgs e)
{
try
{
var c = new MyClass();
c.WriteToFile(textBox1.Text))
MessageBox.Show("success, managed to write to the file");
}
catch(Exception e)
{
MessageBox.Show("Error, Could not write to file. " + e.Message);
}
}
This way, you do not only have the same behaviour, but you also have more information than just the raw fact that your operation was unsuccessful (false)
Okay so I think for you case you don't need a property, but if we assume you wan't to create some kind of wrapper class that handles all your writing to files you could do something along the lines of
class AwesomeFileWriter
{
private const string FileName = "C:\\crypt\\crypt.txt";
private readonly string _text;
public AwesomeFileWriter(string text)
{
_text = text;
}
public bool WriteToFile()
{
try
{
using (System.IO.StreamWriter WriteToFile = new System.IO.StreamWriter(FileName))
{
WriteToFile.Write(_text);
WriteToFile.Close();
}
return true;
}
catch
{
return false;
}
}
}
Without actually showing you the code I'll try and explain getters and setters so you can understand their concept.
A property looks like a method to the internal class and field to an external class.
E.g. You are able to perform logic in your property whereas when you call the property from a different class it behaves just like any other field.
GET: Used to retrieve and return a property. You are able to perform some complex logic before actually returning your property. You are able to safely expose private variables via the Get without compromising on writing.
SET: Used to set the value of a property that may be private, constant or public. You are able to have control over the setting of the variable.
Usually properties are used to keep values as attributes; characteristics; settings.
Methods and functions you would think as actions.
e.g as shown below:
public class MyClass{
/// <summary>
/// Keeps the file name
/// </summary>
public string FileName { get; set; }
/// <summary>
/// Action to write the file
/// </summary>
/// <returns>Returns true if the info. was wrote into the file.</returns>
public bool WriteToFileSucceed()
{
try
{
using (System.IO.StreamWriter WriteToFile = new System.IO.StreamWriter(FileName))
{
WriteToFile.Write(text);
WriteToFile.Close();
}
return true;
}
catch
{
return false;
}
}}
...
public void button1_Click(object sender, EventArgs e){
MyClass myClass = new MyClass();
myClass.FileName = #"C:\crypt\crypt.txt";
if(myClass.WriteToFileSucceed())
{
MessageBox.Show("Success, managed to write to the file");
}
else
{
MessageBox.Show("Ops! Unable to write to the file.");
}}
I'm writing a class called Category which has 2 static methods for retreiving XML data from an external resource. In my example below I'm only going to show one because they're very similar.
What I'm trying to find out is whether this code is "Safe" in terms of invalid URLs, invalid data etc.. basically make it more robust. Here's teh codes
private static string XmlUri
{
get { return "path-to-xml-file"; }
}
private static XDocument XmlFile { get; set; }
public int ID { get; set; }
public string Name { get; set; }
public int Parent { get; set; }
/// <summary>
/// Gets a specific category
/// </summary>
/// <param name="id"></param>
/// <returns>A Category with the specified ID</returns>
public static Category Get(int id)
{
try
{
if (XmlFile == null)
XmlFile = XDocument.Load(XmlUri);
}
// Invalid URL or data
catch (Exception ex)
{
// TODO: Log exception
Console.WriteLine(ex.Message);
}
if (XmlFile == null)
return null;
var cat = from category in XmlFile.Descendants("Category")
where category.Attribute("id").Value.ParseSafe() == id
select new Category
{
ID = category.Attribute("id").Value.ParseSafe(),
Parent = category.Attribute("parent").Value.ParseSafe(),
Name = category.Value
};
return cat.SingleOrDefault();
}
Define 'safe'. Your code will produce null when something is wrong. I would consider a (re-)throw in the catch block after XDocument.Load(). To be safe in not ignoring an invalid URL.
And that puts the ParseSafe() and SingleOrDefault into question as well. What do you want to happen if an id is missing or malformed?
And, a small improvement: You could put the Load-on-Demand logic into the getter of XmlFile. Makes it easier if you also want other elements beside Category.
Not thread safe as ChaosPandion mentioned.
Confusing performance behavior - Get(int) looks like simple fast method, but actually involves non-trivial work. Use lazy initialization and read whole collection of categories onece into dictionary.
Should not catch Exception and swallow it - either use specific ones (I think IOException and XMLExcepetion in this case) or at least let fatal exceptions to be thrown normally.
Obviously if you don't contol XML file it can also cause slownes/hangs while loading insanely large files. Depending on behavior of reader and complexity of XML (if given to you by malicious party) could cause some other exceptions like StackOverflow killing your process.