Skip to main content
Clarify that they are static methods.
Source Link

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods can be static methods to handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception try { var path = NamePath.Parse("..."); // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types:

if (int.TryParse("...", out int age)) { // valid int } else { // invalid int } if (NamePath.TryParse("...", out NamePath path)) { // valid NamePath } else { // invalid NamePath } 

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception try { var path = NamePath.Parse("..."); // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types:

if (int.TryParse("...", out int age)) { // valid int } else { // invalid int } if (NamePath.TryParse("...", out NamePath path)) { // valid NamePath } else { // invalid NamePath } 

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods can be static methods to handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception try { var path = NamePath.Parse("..."); // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types:

if (int.TryParse("...", out int age)) { // valid int } else { // invalid int } if (NamePath.TryParse("...", out NamePath path)) { // valid NamePath } else { // invalid NamePath } 
added 221 characters in body
Source Link
Greg Burghardt
  • 46.5k
  • 8
  • 87
  • 150

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception try { var path = NamePath.Parse("..."); // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types.:

if (int.TryParse("...", out int age)) { // valid int } else { // invalid int } if (NamePath.TryParse("...", out NamePath path)) { // valid NamePath } else { // invalid NamePath } 

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception try { var path = NamePath.Parse("..."); // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types.

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception try { var path = NamePath.Parse("..."); // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types:

if (int.TryParse("...", out int age)) { // valid int } else { // invalid int } if (NamePath.TryParse("...", out NamePath path)) { // valid NamePath } else { // invalid NamePath } 
Clarified code example
Source Link
Greg Burghardt
  • 46.5k
  • 8
  • 87
  • 150

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception   try { var path = NamePath.Parse("...");  // throwsUse properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types.

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

new NamePath(name, lastName); // throws Argument*Exception NamePath.Parse("..."); // throws FormatException if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types.

Throwing exceptions in constructors in C# is fine, but a constructor should always create a valid object. I prefer to keep construction devoid of parsing. Parsing is inherently tricky, because you cannot trust the source of the data. Exceptions should be expected when parsing anything. The .NET stack already has a pattern to deal with this: Parse and TryParse.

While a monad is more idiomatic across languages, the [Try]Parse pattern is a long standing idiom for C#.

The constructor always takes data in the necessary pieces, and throws ArgumentXExceptions in the case invalid arguments are passed. The parse methods handle the parsing either by creating a valid object or throwing a FormatException.

var path = new NamePath(name, lastName); // throws Argument*Exception   try { var path = NamePath.Parse("...");  // Use properly constructed path } catch (FormatException) { // Parse errors } if (NamePath.TryParse("...", out NamePath path)) { // User properly constructed NamePath as path variable } else { // Parse errors } 

This gives code authors some options with how to construct, parse and recover from errors. You'll see this pattern reflected in the native .NET types DateTime, int, decimal, etc. Your custom NamePath type will feel more natural to deal with along side the built-in types.

Source Link
Greg Burghardt
  • 46.5k
  • 8
  • 87
  • 150
Loading