.NET Framework 4.6 and 4.5 – walk-through – (Part 9)

Throwing Exceptions

DO NOT return error codes. Exceptions are the primary means of reporting errors in frameworks.

CONSIDER terminating the process by calling System.Environment.FailFast instead of throwing an exception if your code encounters a situation where it is unsafe for further execution.

Tester-Doer Pattern

The member used to check preconditions of another member is often referred to as a tester, and the member that actually does the work is called a doer. There are cases when the Tester-Doer Pattern can have an unacceptable performance overhead. In such cases, the so-called Try-Parse Pattern should be considered.

Throw rates above 100 per second are likely to noticeably impact the performance of most applications.

Returning exceptions from public APIs instead of throwing them defeats many of the benefits of exception-based error reporting. It is common to throw the same exception from different places. To avoid code bloat, use helper methods that create exceptions and initialize their properties.

DO NOT catch System.Exception or System.SystemException in framework code, unless you intend to rethrowDO NOT throw or derive from ApplicationException.

Throw an InvalidOperationException if the object is in an inappropriate state.

“TryParse / Parse like” pattern: what is the best way to implement it

Prefer using collections over arrays in public APIs.

CONSIDER using jagged arrays instead of multidimensional arrays. A jagged array is an array with elements that are also arrays.

What is jagged array

https://msdn.microsoft.com/en-us/library/2s05feca.aspx

A jagged array is an array whose elements are arrays. The elements of a jagged array can be of different dimensions and sizes. A jagged array is sometimes called an “array of arrays.” The following examples show how to declare, initialize, and access jagged arrays.

 

Multi Dimensional Arrays

https://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx

Types returning enumerators from methods other than GetEnumeratorcannot be used with the foreach statement.

DO NOT return null values from collection properties or from methods returning collections. Return an empty collection or an empty array instead. The general rule is that null and empty (0 item) collections or arrays should be treated the same.

There are numerous books on software patterns, pattern languages, and anti patterns that address the very broad subject of patterns.

Comment from Caribbean Man explains good analogy in OOP.

To understand the difference between objects classes and static members, it is helpful to think of a table in a database. The design of the table, where you specify the field names can be likened to designing your class and specifying the class variables (also called fields). When you start entering data in the table then you create multiple instances of records that are based on the design of the table. This is analogous to instantiating different objects from a class. So a record is to its table, what an object is to its class. So the records in a table can be thought of as being objects instantiated from the table’s design class. Now the table itself would have certain properties that are not limited to any one record but pertain to the table as a whole such as the number of records in the table. the table’s visible property, the width of individual columns, etc. These properties are all table properties and cannot be customized to be different for individual records. This is analogous to the static members of a class. Static members are values that belong to the class as a whole and are shared by, and accessible to each object in the class they cannot be tweaked to be different for each object because there is just one single copy of them that resides with the class itself while being visible outside – if its public or has a public accessor method.

Dependency Properties

A classic example of an attached property is the Grid.Column property. The property represents Button’s (not Grid’s) column position, but it is only relevant if the Button is contained in a Grid, and so it’s “attached” to Buttons by Grids.

Disposable pattern, Dispose Vs Finalize

The CLR provides support for automatic memory management. Managed memory (memory allocated using the C# operator new) does not need to be explicitly released. It is released automatically by the garbage collector (GC). This frees developers from the tedious and difficult task of releasing memory and has been one of the main reasons for the unprecedented productivity afforded by the .NET Framework.

The call to SuppressFinalize should only occur if Dispose(true) executes successfully.

DO declare a protected virtual voidDispose(bool disposing) method to centralize all logic related to releasing unmanaged resources. All resource cleanup should occur in Dispose(bool disposing) method. The method is called from both the finalizer and the IDisposable.Dispose method. The parameter will be false if being invoked from inside a finalizer. It should be used to ensure any code running during finalization is not accessing other finalizable objects. Details of implementing finalizers are described in the next section.

 If you are inheriting from a class that already implements the pattern (Dispose, IDisposable interface), simply override the Dispose(bool) method to provide additional resource cleanup logic.
bad design vs good design on IDisposable implementation

DO NOT make the parameterless Dispose method virtual. The Dispose(bool) method is the one that should be overridden by sub classes.

AVOID throwing an exception from within Dispose(bool) except under critical situations where the containing process has been corrupted (leaks, inconsistent shared state, etc.).

Open Data Protocol (OData) is an open protocol which allows the creation and consumption of queryable and interoperable RESTful APIs in a simple and standard way. Microsoft initiated OData in 2007. Versions 1.0, 2.0, and 3.0 are released under the Microsoft OpenSpecification Promise.

XML documents must contain one and only one root element.

The prolog refers to the information that appears before the start tag of the document or root element. It includes information that applies to the document as a whole, such as character encoding, document structure, and style sheets.

 

The XML declaration is not required, however, if used it must be the first line in the document and no other content or white space can precede it.

processing instruction syntax

The DOCTYPE declaration provides a space for a document to identify its root element and document type definition (DTD) by reference to an external file, through direct declarations, or both.

 

CDATA sections provide a way to tell the parser that there is no markup in the characters contained by the CDATA section. This makes it much easier to create documents containing sections where markup characters might appear, but where no markup is intended. CDATA sections cannot be nested.


sample dtd file

XPath Examples

See full list here: https://msdn.microsoft.com/en-us/library/ms256086(v=vs.110).aspx

Expression Refers to
./author All <author> elements within the current context. Note that this is equivalent to the expression in the next row.
author All <author> elements within the current context.
first.name All <first.name> elements within the current context.
/bookstore The document element (<bookstore>) of this document.
//author All <author> elements in the document.
book[/bookstore/@specialty=@style] All <book> elements whose style attribute value is equal to the specialty attribute value of the <bookstore>element at the root of the document.
author/first-name All <first-name> elements that are children of an <author> element.
bookstore//title All <title> elements one or more levels deep in the <bookstore> element (arbitrary descendants). Note that this is different from the expression in the next row.
bookstore/*/title All <title> elements that are grandchildren of <bookstore> elements.
bookstore//book/excerpt//emph All <emph> elements anywhere inside <excerpt> children of <book> elements, anywhere inside the <bookstore>element.
.//title All <title> elements one or more levels deep in the current context. Note that this situation is essentially the only one in which the period notation is required.
author/* All elements that are the children of <author> elements.
book/*/last-name All <last-name> elements that are grandchildren of <book> elements.
*/* All grandchildren elements of the current context.
*[@specialty] All elements with the specialty attribute.
@style The style attribute of the current context.
price/@exchange The exchange attribute on <price> elements within the current context.
price/@exchange/total Returns an empty node set, because attributes do not contain element children. This expression is allowed by the XML Path Language (XPath) grammar, but is not strictly valid.
book[@style] All <book> elements with style attributes, of the current context.
book/@style The style attribute for all <book> elements of the current context.
@* All attributes of the current element context.
./first-name All <first-name> elements in the current context node. Note that this is equivalent to the expression in the next row.
first-name All <first-name> elements in the current context node.
author[1] The first <author> element in the current context node.
author[first-name][3] The third <author> element that has a <first-name> child.
my:book The <book> element from the my namespace.
my:* All elements from the my namespace.
@my:* All attributes from the my namespace (this does not include unqualified attributes on elements from the mynamespace).
Expression Refers to
x/y[1] The first <y> child of each <x>. This is equivalent to the expression in the next row.
x/y[position() = 1] The first <y> child of each <x>.
(x/y)[1] The first <y> from the entire set of <y> children of <x> elements.
x[1]/y[2] The second <y> child of the first <x>.
Expression Refers to
book[last()] The last <book> element of the current context node.
book/author[last()] The last <author> child of each <book> element of the current context node.
(book/author)[last()] The last <author> element from the entire set of <author> children of <book> elements of the current context node.
book[excerpt] All <book> elements that contain at least one <excerpt> element child.
book[excerpt]/title All <title> elements that are children of <book> elements that also contain at least one <excerpt>element child.
book[excerpt]/author[degree] All <author> elements that contain at least one <degree> element child, and that are children of <book>elements that also contain at least one <excerpt> element.
book[author/degree] All <book> elements that contain <author> children that in turn contain at least one <degree> child.
author[degree][award] All <author> elements that contain at least one <degree> element child and at least one <award> element child.
author[degree and award] All <author> elements that contain at least one <degree> element child and at least one <award> element child.
author[(degree or award) and publication] All <author> elements that contain at least one <degree> or <award> and at least one <publication> as the children
author[degree and not(publication)] All <author> elements that contain at least one <degree> element child and that contain no<publication> element children.
author[not(degree or award) and publication] All <author> elements that contain at least one <publication> element child and contain neither<degree> nor <award> element children.
author[last-name = "Bob"] All <author> elements that contain at least one <last-name> element child with the value Bob.
author[last-name[1] = "Bob"] All <author> elements where the first <last-name> child element has the value Bob. Note that this is equivalent to the expression in the next row.
author[last-name [position()=1]= "Bob"] All <author> elements where the first <last-name> child element has the value Bob.
degree[@from != "Harvard"] All <degree> elements where the from attribute is not equal to "Harvard".
author[. = "Matthew Bob"] All <author> elements whose value is Matthew Bob.
author[last-name = "Bob" and ../price &gt; 50] All <author> elements that contain a <last-name> child element whose value is Bob, and a <price>sibling element whose value is greater than 50.
book[position() &lt;= 3] The first three books (1, 2, 3).
author[not(last-name = "Bob")] All <author> elements that do no contain <last-name> child elements with the value Bob.
author[first-name = "Bob"] All <author> elements that have at least one <first-name> child with the value Bob.
author[* = "Bob"] all author elements containing any child element whose value is Bob.
author[last-name = "Bob" and first-name = "Joe"] All <author> elements that has a <last-name> child element with the value Bob and a <first-name>child element with the value Joe.
price[@intl = "Canada"] All <price> elements in the context node which have an intl attribute equal to "Canada".
degree[position() &lt; 3] The first two <degree> elements that are children of the context node.
p/text()[2] The second text node in each <p> element in the context node.
ancestor::book[1] The nearest <book> ancestor of the context node.
ancestor::book[author][1] The nearest <book> ancestor of the context node and this <book> element has an <author> element as its child.
ancestor::author[parent::book][1] The nearest <author> ancestor in the current context and this <author> element is a child of a <book>element.

Leave a Reply

Your email address will not be published. Required fields are marked *