You are on page 1of 53

More Effective C 50 Specific Ways to

Improve Your C Bill Wagner


Visit to download the full and correct content document:
https://textbookfull.com/product/more-effective-c-50-specific-ways-to-improve-your-c-
bill-wagner/
More products digital (pdf, epub, mobi) instant
download maybe you interests ...

Effective Modern C 42 Specific Ways to Improve Your Use


of C 11 and C 14 1st Edition Scott Meyers

https://textbookfull.com/product/effective-modern-c-42-specific-
ways-to-improve-your-use-of-c-11-and-c-14-1st-edition-scott-
meyers/

Effective Python 90 Specific Ways to Write Better


Python 2nd Edition Brett Slatkin

https://textbookfull.com/product/effective-python-90-specific-
ways-to-write-better-python-2nd-edition-brett-slatkin/

Effective Python 90 specific ways to write better


Python Second Edition Brett Slatkin

https://textbookfull.com/product/effective-python-90-specific-
ways-to-write-better-python-second-edition-brett-slatkin/

Effective C An introduction to professional C


programming 1st Edition Robert C. Seacord

https://textbookfull.com/product/effective-c-an-introduction-to-
professional-c-programming-1st-edition-robert-c-seacord/
Everyday Adventures 50 New Ways to Experience Your
Hometown 1st Edition Lonely Planet

https://textbookfull.com/product/everyday-adventures-50-new-ways-
to-experience-your-hometown-1st-edition-lonely-planet/

50 Ways to Wear Accessories Lauren Friedman

https://textbookfull.com/product/50-ways-to-wear-accessories-
lauren-friedman/

Clean Code with C# - Second Edition: Refactor your


legacy C# code base and improve application performance
using best practices Alls

https://textbookfull.com/product/clean-code-with-c-second-
edition-refactor-your-legacy-c-code-base-and-improve-application-
performance-using-best-practices-alls/

Country Music USA 50th Anniversary Edition Bill C


Malone

https://textbookfull.com/product/country-music-usa-50th-
anniversary-edition-bill-c-malone/

100 Ways to Improve Your Writing Proven Professional


Techniques for Writing with Style and Power Updated
Gary Provost

https://textbookfull.com/product/100-ways-to-improve-your-
writing-proven-professional-techniques-for-writing-with-style-
and-power-updated-gary-provost/
Contents
Introduction

Who Should Read This Book?

About the Content

Code Conventions

Providing Feedback

Acknowledgments

About the Author

1. Working with Data Types

Item 1: Use Properties Instead of Accessible Data Members

Item 2: Prefer Implicit Properties for Mutable Data

Item 3: Prefer Immutability for Value Types

Item 4: Distinguish Between Value Types and Reference Types

Item 5: Ensure That 0 Is a Valid State for Value Types

Item 6: Ensure That Properties Behave Like Data

Item 7: Limit Type Scope by Using Anonymous Types

Item 8: Define Local Functions on Anonymous Types

Item 9: Understand the Relationships Among the Many Different Concepts of


Equality
Item 10: Understand the Pitfalls of GetHashCode()

2. API Design

Item 11: Avoid Conversion Operators in Your APIs

Item 12: Use Optional Parameters to Minimize Method Overloads

Item 13: Limit Visibility of Your Types

Item 14: Prefer Defining and Implementing Interfaces to Inheritance

Item 15: Understand How Interface Methods Differ from Virtual Methods

Item 16: Implement the Event Pattern for Notifications

Item 17: Avoid Returning References to Internal Class Objects

Item 18: Prefer Overrides to Event Handlers

Item 19: Avoid Overloading Methods Defined in Base Classes

Item 20: Understand How Events Increase Runtime Coupling Among Objects

Item 21: Declare Only Nonvirtual Events

Item 22: Create Method Groups That Are Clear, Minimal, and Complete

Item 23: Give Partial Classes Partial Methods for Constructors, Mutators, and
Event Handlers

Item 24: Avoid ICloneable because it limits your design choices

Item 25: Limit Array Parameters to Params Arrays

Item 26: Enable Immediate Error Reporting in Iterators and Async Methods
using Local Functions

3. Task based Asynchronous Programming


Item 27: Use Async methods for async work

Item 28: Never Write Async void Methods

Item 29: Avoid Composing Synchronous and Asynchronous Methods

Item 30: Use async Methods to Avoid Thread Allocations and Context
Switches

Item 31: Avoid Marshalling Context Unnecessarily

Item 32: Compose Asynchronous Work Using Task Objects

Item 33: Consider Implementing the Task Cancellation Protocol

Item 34: Cache Generalized Async Return types

4. Parallel Processing

Item 35: Learn How PLINQ Implements Parallel Algorithms

Item 36: Construct Parallel Algorithms with Exceptions in Mind

Item 37: Use the Thread Pool Instead of Creating Threads

Item 38: Use BackgroundWorker for Cross-Thread Communication

Item 39: Understand Cross-Thread Calls in XAML environments

Item 40: Use lock() as Your First Choice for Synchronization

Item 41: Use the Smallest Possible Scope for Lock Handles

Item 42: Avoid Calling Unknown Code in Locked Sections

5. Dynamic Proramming

Item 43: Understand the Pros and Cons of Dynamic

Item 44: Use Dynamic to Leverage the Runtime Type of Generic Type
Parameters

Item 45: Use DynamicObject or IDynamicMetaObjectProvider for Data-


Driven Dynamic Types

Item 46: Understand How to Make Use of the Expression API

Item 47: Minimize Dynamic Objects in Public APIs

6. Participate in the global C# Community

Item 48: Seek the best answer, not the most popular answer

Item 49: Participate in Specs and Code

Item 50: Consider automating practices with Analyzers


Introduction
C# continues to evolve and change. As the language evolves, the community is
also changing. More C# developers are approaching the language as their first
professional programming language. These members of our community don’t
have the preconceptions common in those of us that started using C# after years
with another C-based language. Even for those that have been using C# for
years, the recent pace of change brings the need for many new habits. The C#
language is seeing an increased pace of innovation in the years since the
compiler has been Open-Sourced. The review of proposed features now
includes the community. The community can participate in the design of the
new features.

Changes in recommended architectures and deployments are also changing the


language idioms we use. Building applications by composing microservices,
distributed programs, data separation from algorithms are all part of modern
application development. The C# language has begun taking steps toward
embracing these different idioms.

I organized this second edition of More Effective C# by taking into account


both the changes in the language and the changes in the C# community. More
Effective C# does not take you on a historical journey through the changes in
the language. Rather, I provide advice on how to use the current C# language.
The items that have been removed from this edition are those that aren’t as
relevant in today’s C# language, or to today’s applications. The new items
cover the new language and framework features, and those practices the
community has learned from building several versions of software products
using C#. Readers of earlier editions will note that content from the previous
edition of Effective C# is included in this edition, and a larger number of items
have been removed. With these editions, I’ve reorganizing both books.
Overall, these 50 items are a set of recommendations that will help you use C#
more effectively as a professional developer.

This book assumes C# 7, but it is not an exhaustive treatment of the new


language features. Like all books in the Effective Software Development
Series, this book offers practical advice on how to use these features to solve
problems you’re likely to encounter every day. I specifically cover C# 7
features where new language features introduce new and better ways to write
common idioms. Internet searches may still point to earlier solutions that have
years of history. I specifically point out older recommendations and why
language enhancements enable better ways.

Many of the recommendations in this book can be validated by Roslyn-based


Analyzers and Code Fixes. I maintain a repository of them here:
https://github.com/BillWagner/MoreEffectiveCSharpAnalyzers. If you have
ideas, or want to contribute, write an issue, or send me a pull request.

Who Should Read This Book?


More Effective C# was written for professional developers for whom C# is
their primary programming language. It assumes you are familiar with the C#
syntax and the language’s features, and are generally proficient in C#. This
book does not include tutorial instruction on language features. Instead, this
book discusses how you can integrate all the features of the current version of
the C# language into your everyday development.

In addition to language features, I assume you have some knowledge of the


Common Language Runtime (CLR) and Just-In-Time (JIT) compiler.

About the Content


Data is ubiquitous. An Object Oriented approach treats data and code as part
of a type and its responsibilities. A Functional approach treats methods as
data. Service oriented approaches separate data from the code that manipulates
it. C# has evolved to contain language idioms that are common in all these
paradigms. That can complicate your design choices. Chapter 1 discusses these
choices and provides guidance on when to pick different language idioms for
different uses.

Programming is API design. It’s how you communicate to your users your
expectations on using your code. It also speaks volumes about your
understanding of other developers’ needs and expectations. In Chapter 2, you’ll
learn the best way to express your intent using the rich palette of C# language
features. You’ll see how to leverage lazy evaluation, create composable
interfaces, and avoid confusion among the various language elements in your
public interfaces.

Task based asynchronous programming provides new idioms for composing


applications from asynchronous building blocks. Mastering these features
means you can create APIs for asynchronous operations that clearly reflect
how that code will execute, and are easy to use. You’ll learn how to use the
Task based asynchronous language support to express how your code executes
across multiple services and using different resources.

Chapter 4 looks at one specific subset of asynchronous programming: mutli-


threaded parallel execution. You’ll see how PLINQ enables easier
decomposition of complex algorithms across multiple cores and multiple
CPUs.

Chapter 5 discusses how to use C# as a dynamic language. C# is a strongly


typed, statically typed language. However, more and more programs contain
both dynamic and static typing. C# provides ways for you to leverage dynamic
programming idioms without losing the benefits of static typing throughout your
entire program. You’ll learn how to use dynamic features and how to avoid
having dynamic types leak through your entire program.

Chapter 6 closes the book with suggestions on how to get involved in the
global C# community. There are more ways to be involved and help to shape
the language you use every day.

Code Conventions
Showing code in a book still requires making some compromises for space and
clarity. I’ve tried to distill the samples down to illustrate the particular point of
the sample. Often that means eliding other portions of a class or a method.
Sometimes that will include eliding error recovery code for space. Public
methods should validate their parameters and other inputs, but that code is
usually elided for space. Similar space considerations remove validation of
method calls, and try/finally clauses that would often be included in
complicated algorithms.

I also usually assume most developers can find the appropriate namespace
when samples use one of the common namespaces. You can safely assume that
every sample implicitly includes the following using statements:
using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;

Providing Feedback
Despite my best efforts, and the efforts of the people who have reviewed the
text, errors may have crept into the text or samples. If you believe you have
found an error, please contact me at bill@thebillwagner.com, or on twitter
@billwagner. Errata will be posted at
http://thebillwagner.com/Resources/MoreEffectiveCS. Many of the items in
this book, are the result of email and twitter conversations with other C#
developers. If you have questions or comments about the recommendations,
please contact me. Discussions of general interest will be covered on my blog
at http://thebillwagner.com/blog.

Acknowledgments
There are many people to whom I owe thanks for their contributions to this
book. I’ve been privileged to be part of an amazing C# community over the
years. Everyone on the C# Insiders mailing list (whether inside or outside
Microsoft) has contributed ideas and conversations that made this a better
book.

I must single out a few members of the C# community who directly helped me
with ideas, and with turning ideas into concrete recommendations.
Conversations with Jon Skeet, Dustin Campbell Kevin Pilch, Jared Parsons,
Scott Allen, most importantly, Mads Torgersen are the basis for many new
ideas in this edition.

I had a wonderful team of technical reviewers for this edition. Jason Bock,
Mark Michaelis, and Eric Lippert pored over the text and the samples to
ensure the quality of the book you now hold. Their reviews were thorough and
complete, which is the best anyone can hope for. Beyond that, they added
recommendations that helped me explain many of the topics better.

The team at Addison-Wesley is a dream to work with. Trina Macdonald is a


fantastic editor, taskmaster, and the driving force behind anything that gets
done. She leans on Mark Renfrow and Olivia Basegio heavily, and so do I.
Their contributions created the quality of the finished manuscript from the front
cover to the back, and everything in between. Curt Johnson continues to do an
incredible job marketing technical content. No matter what format you chose,
Curt has had something to do with its existence for this book.

It’s an honor, once again, to be part of Scott Meyers’s series. He goes over
every manuscript and offers suggestions and comments for improvement. He is
incredibly thorough, and his experience in software, although not in C#, means
he finds any areas where I haven’t explained an item clearly or fully justified a
recommendation. His feedback, as always, is invaluable.

As always, my family gave up time with me so that I could finish this


manuscript. My wife, Marlene, gave up countless hours while I went off to
write or create samples. Without her support, I never would have finished this
or any other book. Nor would it be as satisfying to finish.

About the Author


Bill Wagner is one of the world’s foremost C# developers and a member of
the ECMA C# Standards Committee. He is President of the Humanitarian
Toolbox, has been awarded Microsoft Regional Director and .NET MVP for
11 years, and was recently appointed to the .NET Foundation Advisory
Council. Wagner has worked with companies ranging from start-ups to
enterprises improving the software development process and growing their
software development teams. He is currently with Microsoft, working on the
.NET Core content team. He creates learning materials for developers
interested in the C# language and .NET Core. Bill earned a B.S. in computer
science from the University of Illinois at Champaign-Urbana.
1. Working with Data Types
C# was originally designed to support object oriented design techniques,
where data and functionality are brought together. As it has matured, it has
added new idioms to support programming practices that have become more
common. One of those trends is to separate data storage concerns from the
methods that manipulate that data. This trend is driven by the move to
distributed systems, where an application is decomposed into many smaller
services that each implement single features, or a small set of related features.
Moving to a new strategy for separating concerns gives rise to new
programming techniques. Using new programming techniques gives rise to new
language features.

In this chapter, you’ll learn techniques to separate data from the methods that
manipulate or process that data. It’s not always objects. Sometimes it’s
functions and passive data containers.

Item 1: Use Properties Instead of Accessible Data


Members
Properties have always been a feature of the C# language. Several
enhancements since the initial release of the C# language have made properties
even more expressive. You can specify different access restrictions on the
getter and setter. Auto properties minimize the hand typing for properties
instead of data members, including readonly properties. Expression bodied
members enable even more concise syntax. If you’re still creating public fields
in your types, stop now. If you’re still creating get and set methods by hand,
stop now. Properties let you expose data members as part of your public
interface and still provide the encapsulation you want in an object-oriented
environment. Properties are language elements that are accessed as though they
are data members, but they are implemented as methods.

Some members of a type really are best represented as data: the name of a
customer, the (x,y) location of a point, or last year’s revenue. Properties enable
you to create an interface that acts like accessing data fields directly but still
has all the benefits of a method. Client code accesses properties as though they
are accessing public fields. But the actual implementation uses methods, in
which you define the behavior of property accessors.

The .NET Framework assumes that you’ll use properties for your public data
members. In fact, the data binding classes in the .NET Framework support
properties, not public data fields. This is true for all the data binding libraries:
WPF, Windows Forms, and Web Forms. Data binding ties a property of an
object to a user interface control. The data binding mechanism uses reflection
to find a named property in a type:

textBoxCity.DataBindings.Add("Text",
address, nameof(City));

The previous code binds the Text property of the textBoxCity control to the
City property of the address object. It will not work with a public data field
named City; the Framework Class Library designers did not support that
practice. Public data members are bad practice, so support for them was not
added. Their decision simply gives you yet another reason to follow the proper
object-oriented techniques.

Yes, data binding applies only to those classes that contain elements that are
displayed in your user interface logic. But that doesn’t mean properties should
be used exclusively in UI logic. You should use properties for other classes
and structures. Properties are far easier to change as you discover new
requirements or behaviors over time. You might soon decide that your
customer type should never have a blank name. If you used a public property
for Name, that’s easy to fix in one location:
public class Customer
{
private string name;
public string Name
{
get => name;
set
{
if (string.IsNullOrWhitespace(value))
throw new ArgumentException(
"Name cannot be blank",
nameof(Name));
name = value;
}
// More Elided.
}
}

If you had used public data members, you’re stuck looking for every bit of
code that sets a customer’s name and fixing it there. That takes more time—
much more time.

Because properties are implemented with methods, adding multithreaded


support is easier. You can enhance the implementation of the get and set
accessors to provide synchronized access to the data (See Item 38 for more
details):
public class Customer
{
private object syncHandle = new object();

private string name;


public string Name
{
get
{
lock (syncHandle)
return name;
}
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"Name cannot be blank",
nameof(Name));
lock (syncHandle)
name = value;
}
}
// More Elided.
}

Properties have the language features of methods. Properties can be virtual:


public class Customer
{
public virtual string Name
{
get;
set;
}
}

You’ll notice that the last examples use the implicit property syntax. Creating a
property to wrap a backing store is a common pattern. Often, you won’t need
validation logic in the property getters or setters. The language supports the
simplified implicit property syntax to decrease the amount of ceremonial code
needed to expose a simple field as a property. The compiler creates a private
field (typically called a backing store) for you and implements the obvious
logic for both the get and set accessors.

You can extend properties to be abstract and define properties as part of an


interface definition, using similar syntax to implicit properties. The example
below shows a property definition in a generic interface. Note that while the
syntax is consistent with implicit properties, the interface definition below
does not include any implementation. It defines a contract that must be satisfied
by any type that implements this interface.
public interface INameValuePair<T>
{
string Name { get; }

T Value { get; set; }


}

Properties are full-fledged, first-class language elements that are an extension


of methods that access or modify internal data. Anything you can do with
member functions, you can do with properties. Properties do not allow one
other important source of breakage possible that is possible with fields: You
cannot pass a property to a method using the ref or out keywords.

The accessors for a property are two separate methods that get compiled into
your type. You can specify different accessibility modifiers to the get and set
accessors in a property in C#. This gives you even greater control over the
visibility of those data elements you expose as properties:
public class Customer
{
public virtual string Name
{
get;
protected set;
}
// remaining implementation omitted
}

The property syntax extends beyond simple data fields. If your type should
contain indexed items as part of its interface, you can use indexers (which are
parameterized properties). It’s a useful way to create a property that returns the
items in a sequence:
public int this[int index]
{
get => theValues[index];
set => theValues[index] = value;
}
private int[] theValues = new int[100];

// Accessing an indexer:
int val = someObject[i];

Indexers have all the same language support as single-item properties: They
are implemented as methods you write, so you can apply any verification or
computation inside the indexer. Indexers can be virtual or abstract, can be
declared in interfaces, and can be read-only or read-write. Single-dimension
indexers with numeric parameters can participate in data binding. Other
indexers can use noninteger parameters to define maps:
public Address this[string name]
{
get => addressValues[name];
set => addressValues[name] = value;
}
private Dictionary<string, Address> addressValues;

In keeping with the multidimensional arrays in C#, you can create


multidimensional indexers, with similar or different types on each axis:
public int this[int x, int y]
=> ComputeValue(x, y);
public int this[int x, string name]
=> ComputeValue(x, name);

Notice that all indexers are declared with the this keyword. You cannot name
an indexer in C#. Therefore, every different indexer in a type must have
distinct parameter lists to avoid ambiguity. Almost all the capabilities for
properties apply to indexers. Indexers can be virtual or abstract; indexers can
have separate access restrictions for setters and getters. You cannot create
implicit indexers as you can with properties.

This property functionality is all well and good, and it’s a nice improvement.
But you might still be tempted to create an initial implementation using data
members and then replace the data members with properties later when you
need one of those benefits. That sounds like a reasonable strategy—but it’s
wrong. Consider this portion of a class definition:
// using public data members, bad practice:
public class Customer
{
public string Name;

// remaining implementation omitted


}

It describes a customer, with a name. You can get or set the name using the
familiar member notation:
string name = customerOne.Name;
customerOne.Name = "This Company, Inc.";

That’s simple and straightforward. You are thinking that you could later
replace the Name data member with a property, and the code would keep
working without any change. Well, that’s sort of true. Properties are meant to
look like data members when accessed. That’s the purpose behind the syntax.
But properties are not data. A property access generates different Microsoft
Intermediate Language (MSIL) instructions than a data access.

Although properties and data members are source compatible, they are not
binary compatible. In the obvious case, this means that when you change from a
public data member to the equivalent public property, you must recompile all
code that uses the public data member. C# treats binary assemblies as first-
class citizens. One goal of the language is that you can release a single updated
assembly without upgrading the entire application. The simple act of changing
a data member to a property breaks binary compatibility. It makes upgrading
single assemblies that have been deployed much more difficult.

While looking at the IL for a property, you probably wonder about the relative
performance of properties and data members. Properties will not be faster than
data member access, but they might not be any slower. The JIT compiler does
inline some method calls, including property accessors. When the JIT compiler
does inline property accessors, the performance of data members and
properties is the same. Even when a property accessor has not been inlined,
the actual performance difference is the negligible cost of one function call.
That is measurable only in a small number of situations.

Properties are methods that can be viewed from the calling code like data.
That puts some expectations into your users’ heads. They will see a property
access as though it was a data access. After all, that’s what it looks like. Your
property accessors should live up to those expectations. Get accessors should
not have observable side effects. Set accessors do modify the state, and users
should be able to see those changes.

Property accessors also have performance expectations for your users. A


property access looks like a data field access. It should not have performance
characteristics that are significantly different than a simple data access.
Property accessors should not perform lengthy computations, or make cross-
application calls (such as perform database queries), or do other lengthy
operations that would be inconsistent with your users’ expectations for a
property accessor.

Whenever you expose data in your type’s public or protected interfaces, use
properties. Use an indexer for sequences or dictionaries. All data members
should be private, without exception. You immediately get support for data
binding, and you make it much easier to make any changes to the
implementation of the methods in the future. The extra typing to encapsulate any
variable in a property amounts to one or two minutes of your day. Finding that
you need to use properties later to correctly express your designs will take
hours. Spend a little time now, and save yourself lots of time later.
Item 2: Prefer Implicit Properties for Mutable Data
Additions to the property syntax mean that you can express your design intent
clearly using properties. The modern C# syntax also supports changes to your
design over time. Start with properties, and you enable many future scenarios.

When you add accessible data to a class, often the property accessors are
simple wrappers around your data fields. When that’s the case, you can
increase the readability of your code by using implicit properties:

public string Name { get; set; }

The compiler creates the backing field using a compiler-generated name. You
can even use the property setter to modify the value of the backing field.
Because the name of the backing field is compiler generated, even inside your
own class you need to call the property accessor rather than modify the
backing field directly. That’s not a problem. Calling the property accessor
does the same work, and because the generated property accessor is a single
assignment statement, it will likely be inlined. The runtime behavior of the
implicit property is the same as the runtime behavior of accessing the backing
field, even in terms of performance.

Implicit properties support the same property access specifiers as do their


explicit counterparts. You can define any more-restrictive set accessor you
need:

public string Name


{
get;
protected set;
}
// Or
public string Name
{
get;
internal set;
}
// Or
public string Name
{
get;
protected internal set;
}
// Or
public string Name
{
get;
private set;
}
// Or
// Can only be set in constructor:
public string Name { get; }

Implicit properties create the same pattern of a property with a backing field
that you would have typed yourself in previous versions of the language. The
advantage is that you are more productive, and your classes are more readable.
An implicit property declaration shows anyone reading your code exactly what
you intended to produce, and it doesn’t clutter the file with extra information
that only obscures the real meaning.

Of course, because implicit properties generate the same code as explicit


properties, you can use implicit properties to define virtual properties,
override virtual properties, or implement a property defined in an interface.

When you create a virtual implicit property, derived classes do not have
access to the compiler-generated backing store. However, overrides can
access the base property get and set methods just as they can with any other
virtual method:

public class BaseType


{
public virtual string Name
{
get;
protected set;
}
}

public class DerivedType : BaseType


{
public override string Name
{
get => base.Name;
protected set
{
if (!string.IsNullOrEmpty(value))
base.Name = value;
}
}
}

You gain two additional advantages by using implicit properties. When the
time comes to replace the implicit property with a concrete implementation
because of data validation or other actions, you are making binary-compatible
changes to your class, and your validation will be in only one location.

In earlier versions of the C# language, most developers directly accessed the


backing field to modify it in their own class. That practice produces code that
distributes the validation and error checking throughout the file. Every change
to an implicit property’s backing field calls the (possibly private) property
accessor. You transform the implicit property accessor to an explicit property
accessor, and then you write all the validation logic in the new accessor:
// original version
public class Person
{
public string FirstName { get; set;}
public string LastName { get; set; }
public override string ToString() =>
$"{FirstName} {LastName}";
}

// Later updated for validation


public class Person
{
public Person(string firstName, string lastName)
{
// leverage validation in property setters:
this.FirstName = firstName;
this.LastName = lastName;
}
private string firstName;
public string FirstName
{
get => firstName;
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"First name cannot be null or empty");
firstName = value;
}
}

private string lastName;


public string LastName
{
get => lastName;
private set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"Last name cannot be null or empty");
lastName = value;
}
}
public override string ToString() =>
$"{FirstName} {LastName}";
}

You’ve created all the validation in one place. If you can continue to use your
accessor rather than directly access the backing field, then you can continue to
keep all the field validation in one location.

There is one important limitation of implicit properties. You cannot use


implicit properties on types that are decorated with the Serializable
attribute. The persistent file storage format depends on the name of the
compiler-generated field used for the backing store. That field name is not
guaranteed to remain constant. It may change at any time when you modify the
class.

In spite of those two limitations, implicit properties save developer time,


produce readable code, and promote a style of development in which all your
field modification validation code happens in one location. If you create
clearer code, it helps you maintain that code in a better way.

Item 3: Prefer Immutability for Value Types


Immutable types are simple: After they are created, they are constant. If you
validate the parameters used to construct the object, you know that it is in a
valid state from that point forward. You cannot change the object’s internal
state to make it invalid. You save yourself a lot of otherwise necessary error
checking by disallowing any state changes after an object has been constructed.
Immutable types are inherently thread safe: Multiple readers can access the
same contents. If the internal state cannot change, there is no chance for
different threads to see inconsistent views of the data. Immutable types can be
exported from your objects safely. The caller cannot modify the internal state
of your objects. Immutable types work better in hash-based collections. The
value returned by Object.GetHashCode() must be an instance invariant (see
Item 7); that’s always true for immutable types.

In practice, it is very difficult to make every type immutableThat’s why this


recommendation is for both atomic and immutable value types. Decompose
your types to the structures that naturally form a single entity. An Address type
does form such an entity. An address is a single thing, composed of multiple
related fields. A change in one field likely means changes to other fields. A
customer type is not an atomic type. A customer type will likely contain many
pieces of information: an address, a name, and one or more phone numbers.
Any of these independent pieces of information might change. A customer
might change phone numbers without moving. A customer might move, yet still
keep the same phone number. A customer might change his or her name without
moving or changing phone numbers. A customer object is not atomic; it is built
from many different immutable types using composition: an address, a name, or
a collection of phone number/type pairs. Atomic types are single entities: You
would naturally replace the entire contents of an atomic type. The exception
would be to change one of its component fields.

Here is a typical implementation of an address that is mutable:


// Mutable Address structure.
public struct Address
{
private string state;
private int zipCode;

// Rely on the default system-generated


// constructor.

public string Line1 { get; set; }


public string Line2 { get; set; }
public string City { get; set; }
public string State
{
get => state;
set
{
ValidateState(value);
state = value;
}
}

public int ZipCode


{
get => zipCode;
set
{
ValidateZip(value);
zipCode = value;
}
}

// other details omitted.


}

// Example usage:
Address a1 = new Address();
a1.Line1 = "111 S. Main";
a1.City = "Anytown";
a1.State = "IL";
a1.ZipCode = 61111;
// Modify:
a1.City = "Ann Arbor"; // Zip, State invalid now.
a1.ZipCode = 48103; // State still invalid now.
a1.State = "MI"; // Now fine.

Internal state changes mean that it’s possible to violate object invariants, at
least temporarily. After you have replaced the City field, you have placed a1 in
an invalid state. The city has changed and no longer matches the state or ZIP
code fields. The code looks harmless enough, but suppose that this fragment is
part of a multithreaded program. Any context switch after the city changes and
before the state changes would leave the potential for another thread to see an
inconsistent view of the data.

Okay, so you think you’re not writing a multithreaded program. You can still
get into trouble. Imagine that the ZIP code was invalid and the set threw an
exception. You’ve made only some of the changes you intended, and you’ve left
the system in an invalid state. To fix this problem, you would need to add
considerable internal validation code to the address structure. That validation
code would add considerable size and complexity. To fully implement
exception safety, you would need to create defensive copies around any code
block in which you change more than one field. Thread safety would require
adding significant thread-synchronization checks on each property accessor,
both sets and gets. All in all, it would be a significant undertaking—and one
that would likely be extended over time as you add new features.

Instead, if you need Address to be a struct, make it immutable. Start by


changing all instance fields to read-only for outside uses.
public struct Address
{
// remaining details elided
public string Line1 { get; }
public string Line2 { get; }
public string City { get; }
public string State { get; }
public int ZipCode { get; }

public Address(string line1,


string line2,
string city,
string state,
int zipCode) :
this()
{
Line1 = line1;
Line2 = line2;
City = city;
ValidateState(state);
State = state;
ValidateZip(zipCode);
ZipCode = zipCode;
}
}

Now you have an immutable type, based on the public interface. To make it
useful, you need to add all necessary constructors to initialize the Address
structure completely. The Address structure needs only one additional
constructor, specifying each field. A copy constructor is not needed because
the assignment operator is just as efficient. Remember that the default
constructor is still accessible. There is a default address where all the strings
are null, and the ZIP code is 0:
public Address(string line1,
string line2,
string city,
string state,
int zipCode) :
this()
{
Line1 = line1;
Line2 = line2;
City = city;
ValidateState(state);
State = state;
ValidateZip(zipCode);
ZipCode = zipCode;
}

Using the immutable type requires a slightly different calling sequence to


modify its state. You create a new object rather than modify the existing
instance:
// Create an address:
Address a2 = new Address("111 S. Main",
"", "Anytown", "IL", 61111);

// To change, re-initialize:
a2 = new Address(a1.Line1,
a1.Line, "Ann Arbor", "MI", 48103);

The value of a1 is in one of two states: its original location in Anytown, or its
updated location in Ann Arbor. You do not modify the existing address to
create any of the invalid temporary states from the previous example. Those
interim states exist only during the execution of the Address constructor and
are not visible outside that constructor. As soon as a new Address object is
constructed, its value is fixed for all time. It’s exception safe: a1 has either its
original value or its new value. If an exception is thrown during the
construction of the new Address object, the original value of a1 is unchanged.

To create an immutable type, you need to ensure that there are no holes that
would allow clients to change your internal state. Value types do not support
derived types, so you do not need to defend against derived types modifying
fields. But you do need to watch for any fields in an immutable type that are
mutable reference types. When you implement your constructors for these
types, you need to make a defensive copy of that mutable type. All these
examples assume that Phone is an immutable value type because we’re
concerned only with immutability in value types:
// Almost immutable: there are holes that would
// allow state changes.
public struct PhoneList
{
private readonly Phone[] phones;

public PhoneList(Phone[] ph)


{
phones = ph;
}

public IEnumerable<Phone> Phones


{
get { return phones; }
}
}

Phone[] phones = new Phone[10];


// initialize phones
PhoneList pl = new PhoneList(phones);

// Modify the phone list:


// also modifies the internals of the (supposedly)
// immutable object.
phones[5] = Phone.GeneratePhoneNumber();

The array class is a reference type. The array referenced inside the PhoneList
structure refers to the same array storage (phones) allocated outside the object.
Developers can modify your immutable structure through another variable that
refers to the same storage. To remove this possibility, you need to make a
defensive copy of the array.. Array is a mutable type. One alternative would
be to use the ImmutableArray class, in the
System.Collections.Immutable namespace. The previous example shows
the pitfalls of a mutable collection. Even more possibilities for mischief exist
if the Phone type is a mutable reference type. Clients could modify the values
in the collection, even if the collection is protected against any modification.
This is easy using the ImmutableList collection type:

public struct PhoneList


{
private readonly ImmutableList<Phone> phones;

public PhoneList(Phone[] ph)


{
phones = ph.ToImmutableList();
}

public IEnumerable<Phone> Phones => phones;


}

The complexity of a type dictates which of three strategies you will use to
initialize your immutable type. The Address structure defined one constructor
to allow clients to initialize an address. Defining the reasonable set of
constructors is often the simplest approach.

You can also create factory methods to initialize the structure. Factories make
it easier to create common values. The .NET Framework Color type follows
this strategy to initialize system colors. The static methods
Color.FromKnownColor() and Color.FromName() return a copy of a color
value that represents the current value for a given system color.

Third, you can create a mutable companion class for those instances in which
multistep operations are necessary to fully construct an immutable type. The
.NET string class follows this strategy with the
System.Text.StringBuilder class. You use the StringBuilder class to
create a string using multiple operations. After performing all the operations
necessary to build the string, you retrieve the immutable string from the
StringBuilder.

Immutable types are simpler to code and easier to maintain. Don’t blindly
create get and set accessors for every property in your type. Your first choice
for types that store data should be immutable, atomic value types. You easily
can build more complicated structures from these entities.

Item 4: Distinguish Between Value Types and


Reference Types
Value types or reference types? Structs or classes? When should you use each?
This isn’t C++, in which you define all types as value types and can create
references to them. This isn’t Java, in which everything is a reference type
(unless you are one of the language designers). You must decide how all
instances of your type will behave when you create it. It’s an important
decision to get right the first time. You must live with the consequences of your
decision because changing later can cause quite a bit of code to break in subtle
ways. It’s a simple matter of choosing the struct or class keyword when you
create the type, but it’s much more work to update all the clients using your
type if you change it later.

It’s not as simple as preferring one over the other. The right choice depends on
how you expect to use the new type. Value types are not polymorphic. They are
better suited to storing the data that your application manipulates. Reference
types can be polymorphic and should be used to define the behavior of your
application. Consider the expected responsibilities of your new type, and from
those responsibilities, decide which type to create. Structs store data. Classes
define behavior.

The distinction between value types and reference types was added to .NET
and C# because of common problems that occurred in C++ and Java. In C++,
all parameters and return values were passed by value. Passing by value is
very efficient, but it suffers from one problem: partial copying (sometimes
called slicing the object). If you use a derived object where a base object is
expected, only the base portion of the object gets copied. You have effectively
lost all knowledge that a derived object was ever there. Even calls to virtual
functions are sent to the base class version.

The Java language responded by more or less removing value types from the
language. All user-defined types are reference types. In the Java language, all
parameters and return values are passed by reference. This strategy has the
advantage of being consistent, but it’s a drain on performance. Let’s face it,
some types are not polymorphic—they were not intended to be. Java
programmers pay a heap allocation and an eventual garbage collection for
every object instance. They also pay an extra time cost to dereference every
Another random document with
no related content on Scribd:
“You forget,” said Lady Clarice, hastily. “It was not publicly
known.”
So, then, Lady Hermione was still free—no adoring husband or
jealous lover was there. He would rather ten thousand times over
been told that she was married and was most passionately attached
to her husband; that would have been better news for him; the
barrier between them would have been doubled. He did not like to
think that any time he went out he should meet her, perhaps more
beautiful than ever, to renew all his misery. He had all the respect of
a true, pure-hearted Englishman for the sanctity of the marriage tie,
and he wished that the barrier between himself and the woman he
loved were as great and strong on her side as on his.
“Clarice,” he said to his wife, “I have altered my mind. Nay, you
are going to tell me that I am claiming a woman’s privilege; let it be
so. I am not much stronger than a woman in some things. I shall not
invite the Lorristons to Aldenmere.”
She looked up at him with a sudden cloud of anxiety on her face.
“Why, Ronald?”
“It would not be pleasant. After all, they did not behave well to
me. We had better, I think, keep that distance that seems to have
grown between us.”
Lady Clarice was perfectly willing, nothing could have pleased
her better, for there was no time of her life during which she had not
been more or less jealous of Lady Hermione.
CHAPTER XXII.
IN HOLME WOODS.

So during all the wedding festivities with which the whole country
rang the Lorristons were away; there was not even the civility of a
letter exchanged between them. People did not quite know what the
difference was about; but a quiet understanding soon came about
that the Lorristons and the Aldens should never be invited together.
For Sir Ronald the second phase of his life began when, as the
husband of another woman, it was more than ever his duty to
trample under foot the passion that marred his life. Then, in sober
earnest, he had to take up the duties of life and make the best of
them.
He was kind and attentive to his beautiful young wife; he was
careful in the fulfillment of his duties; but in the silent depths of his
own heart there was no moment, night or day, in which he did not,
with the most bitter words, curse his own fate. So the remainder of
that summer passed. Winter brought its usual round of country
gayeties. In this season Sir Ronald and Lady Clarice went to
London, where her beauty and fascination created a perfect furore.
There, for the first time, he heard that the Lorristons had not come to
town because Lady Hermione had been long out of health. She was
not ill—that is, not ill enough to alarm her friends, but she was unfit
to encounter the fatigues of a London season.
When it was over Sir Ronald and his wife returned to Aldenmere.
One day toward the end of the month of June, Sir Ronald went
out into the Holme Woods. The morning was fine, the sun shining,
and the air filled with the fragrance of wild flowers. Holme Woods
had never looked so beautiful. The trees wore their richest foliage,
great sheets of blue hyacinths spread out far and wide, bright-
winged butterflies hovered over them, bees hummed for very joy at
the rich feast spread before them. Sir Ronald had not noticed the
path he was taking. The faint, wild perfume of the harebells was
grateful to him. Body, mind, heart and soul, he was tired, and he had
come to the woods, loving the solitude he found there.
You know, reader, what face was before him. Imagine his surprise
when his thoughts suddenly seemed embodied; for there, seated on
a bank, with the pretty harebells nodding around her, was Lady
Hermione Lorriston.
He would have turned and fled, but the manhood within him
rebelled against flight. He stood looking helplessly at her, too
bewildered for words. When he was capable of coherent thought he
saw how white her face grew. She rose and stood before him, like
some bright, strange, frightened bird, dreading to stay, yet dreading
to go.
And then the past months, with their untold agony, faded from
him. He remembered nothing save that it was summer time and he
loved her—save that for him it was heaven where she was, and a
dreary blank where she was not.
“Hermione!” he cried, going up to her, and holding out his hand,
all his proud resolves, all his hauteur, all his indignant anger melted
into thin air.
She gave him no hand in return. The pale, sweet face was graver
than he had ever seen it before.
“I did not think to see you here, Sir Ronald,” she said, coldly.
He had only seen her once since the night when he had kissed
her among the flowers, and everything save the memory of that night
seemed to die from him.
“How cruel you have been to me, Hermione; how you lured me
on to my ruin and my doom; how false you are despite the fairness
of that most fair face! If you had stabbed me, and trampled my dead
body under foot, you would have been less cruel. What did I ever do,
Hermione, that I deserved so cruel a fate?”
She looked up at him proudly.
“You have no right to speak to me,” she said. “You are married,
and the kindness or cruelty of no other woman but your wife should
concern you. Then I have not been cruel to you, Ronald, and you
know it.”
There was something inexpressibly sad and pitiful in the whole
scene. These two, who loved each other so dearly, who in the whole
world cared only for each other, parted more completely than if death
had separated them.
“I know that you did me the greatest wrong woman could do to
man,” he replied.
“What was it?” she asked, the proud flush deepening on her face.
“You led me to believe you cared for me—you gave to me looks
and words such as you gave to no other man—you let me kiss your
lips and did not say me nay; then, when I had grown bold through
your kindness, and prayed the prayer that for long months had been
on my lips, you slew me with cruel, scornful words.”
“I do not understand you,” she said, quietly.
“You will not, rather. I say again, Hermione, that you have played
with me more cruelly than a cat plays with a mouse. You have
laughed at my torture.”
“You are speaking most falsely,” she said.
“Let God judge between us. I lay the ruin of my life upon you. I
say you deliberately deceived me.”
“I deny it,” she replied. “How could I be cruel or false to you. I
have had no opportunity of being either. I have never heard of you or
seen you but once since the evening of my birthday!”
“You have written to me, and it is of your written words I
complain.”
“I have never in all my life written one line to you,” she said,
earnestly.
“You have never written to me, Hermione? Ah, do not stain those
lips with a lie!”
“I never have,” she repeated, with a deep-drawn sob. “Listen! I
swear it before the most high God.”
And then for some minutes they stood looking bewildered and
wonderingly at each other.
CHAPTER XXIII.
BAD MADE WORSE.

Sir Ronald came nearer to Lady Hermione; his face was white
and stern, his eyes gleamed with an angry light.
“Let me ask you a plain question, Lady Hermione. Perhaps this
conversation had been better left alone. Having commenced it, I
must know more than you have said. You must not refuse to answer
me. Either you are deceiving me now, or I have been tricked more
foully than man ever was before. I must know which it is.”
“I am not deceiving you; why should I? Deceit is foreign to me; I
abhor it. I repeat what I have said. It is possible that I may have
addressed cards of invitation to you; but in my whole life I have
never written to you one single letter.”
Looking into her pale, sweet face, where all truth, purity and
goodness reigned, it was not possible to doubt her.
“Hermione,” he said, more gently, “you remember the evening of
the ball?”
“Yes,” she said, sadly, “I remember it well.”
“We stood among the roses, you and I, the moon shining, the
distant sound of music floating near us. You did not chide me when I
kissed your lips, and I—oh, blind fool that I was!—I looked upon that
kiss as a solemn betrothal.”
She shrank from the passionate tones of his voice, then looked at
him.
“I made the same mistake,” she said, simply, “and I have paid
very dearly for it.”
“Then, for a whole week afterward, Hermione, I went to Leeholme
every day. I tried hard to find an opportunity of speaking to you; you
were always surrounded by people. There were times, even, when I
imagined you felt a delight in baffling what you must have known to
be my heart’s desire.”
“It was but a girlish delight in mischief,” she interrupted; “and, ah
me! the bitter price I have paid.”
“I wrote to you,” he continued, “finding that there was no chance
of speaking. I wrote and told you how most dearly I loved you, and
prayed you to be my wife. What was your answer to that prayer?”
He looked into her face as he asked the question; it was so
sweet, sad and sorrowful, but there was no untruth to mar its beauty.
The wind stirred the bluebells faintly, and a deep, soft sigh shivered
through them.
“What was your answer to my prayer?” he repeated.
“None,” she replied. “I never received such a letter; therefore, I
could not answer it.”
“Say that again,” he gasped, in a thick, hoarse voice.
“I never received it, Ronald. This is the first word I have ever
heard of it.”
He reeled as though one had struck him a sudden, mortal blow.
The sweet, soft voice continued sadly:
“You have not thought more hardly of me than I of you. I believed
that night you loved me, and I was—well, it does not matter how
happy; then you came and went without saying one word. Suddenly
you absented yourself altogether; you never came near me. I met
you, and you avoided me. I knew no more until I heard and knew
that you were going to Mount Severn.”
His face was not pleasant to look upon as she uttered these
words.
“Then you never read it, Hermione, or knew of my writing at all?”
“Not one word,” she said, earnestly.
There were a few moments of silence, unbroken save by the
wind among the harebells.
“Answer me only one more question, and I have done,” he said.
“If you had received my letter, what would your answer have been?”
The light he remembered so well came into her face; for a few
moments she forgot the barrier between them that could never be
passed.
“You know what it would have been, Ronald. I—I should have
said ‘Yes,’ because I have loved you, and you alone, all my life.”
Then the words died on her lips, for, strong and brave as he was,
he had flung himself face downward among the harebells, and lay
there, sobbing like a child.
A strong man’s tears are terrible to see. Women weep, and,
though one pities them, it seems but natural. When a proud, self-
controlled, high-spirited man breaks down and weeps, the grief is
terrible to witness.
So she thought who bent over him now with soothing words.
“Ronald, you will break my heart if you do this. There has been a
terrible mistake, but it will be made right for us in another world. We
have one comfort—we did love each other. God knows what has
parted us; it is not untruth or falsity. Oh, Ronald! does it not comfort
you to know this?”
All that answered her was the deep-drawn, bitter sobs that shook
his strong frame, and the sweet, rustling sound of the bells in the
breeze.
“If I had been false to you, as you believed, Ronald, the memory
of me would have been a lifelong pain. If you had been false to me,
the very thought of you would have been a perpetual sorrow; but
now we may remember without sin that we once loved each other in
all truth.”
She was startled when he raised his face to her, and clutched her
hand in his strong grasp.
“Oh, my lost love, my lost, dearest, only love! what has parted
us? Tell me! I must know—I will know!”
“I cannot tell,” she replied, gently laying her white, cool, soft hand
on his hot brow. “I cannot even imagine. All I am certain of is that I
never until this morning even heard of such a letter.”
“Who has done it?” he cried, wildly. “Oh, Hermione, do you know
I have been mad for love of you, and for the loss of you? Do you
know that, after I believed you rejected me, I have lived like a man
without reason, without soul? My days and nights have been one
long dream of anguish, one long madness. I hate the sun that
shines, the night that succeeds day, for no time will ever bring you
back to me, and without you life is death.”
“You forget,” she interrupted, gently. “You have your wife, Clarice,
who loves you.”
“I do not forget. Poor Clarice!—God pity her and pity me! I do not
love her, Hermione. I have tried as hard to love her as I have to
forget you, but cannot. I pray Heaven to pardon me the wrong I did in
marrying her; I was blind enough to think it for the best. Oh, my lost
love, I am going mad! Lay your cool hands on my brow again; fight
down the demons who master me, my angel, my loadstar, my
treasure! And you would have married me, Hermione? You would
have made my life heaven instead of what it is. I might have been
the happiest, even as I am the most wretched, of men.”
“It might have been so; but, Ronald, you must not talk so to me. I
am so glad I have seen you—glad to know you were not fickle in
love and fancy, as I thought; but now we must part, and we must not
meet again.”
“I know; but before you leave me, Hermione, tell me how it
happened?”
“I cannot; how did you send that letter to me, Ronald?”
“By my groom. He had orders to deliver it into your own hands,
but you were away. He waited some hours, and, as you did not
return, he gave it to your maid. I asked him every particular.”
“To my maid! She never gave me any letter from you, Ronald.
When did you send it?”
“It was exactly one week after the ball,” he replied.
“I remember,” said Lady Hermione. “We had all been over to
Thringston, and it was late when we returned. My maid told me there
was an envelope on the toilet-table that Sir Ronald’s groom had
brought.”
“That was it,” he said, eagerly.
“No,” she said; “there is some mistake. I opened it, and there was
nothing inside but a white rose, carefully folded. I laughed at what
seemed to me a romantic idea.”
“Was the envelope addressed to you?” he asked, quickly.
“Yes, and in your handwriting. I knew it at once.”
“There must have been foul play,” he said.
“But how, Ronald? You spoke of a letter from me; tell me of that.”
“It was an answer to mine; it came by post a day afterward. It was
in your handwriting, I swear, and it—rejected me.”
“I cannot understand it,” she cried.
“Nor I. But if it takes the whole of my life to find it out, it shall not
remain a mystery,” he said; and then he stood erect and silent before
her.
CHAPTER XXIV.
FAREWELL.

While she lived Lady Hermione never forgot the look of anguish
that he gave her; a long, lingering, steady gaze such as a dying man
fixes at times on the face of a beloved wife or child. Then he came a
step nearer to her.
“I did not know, Hermione,” he said, “that life could be harder than
I have hitherto found it. It will be harder now.”
“Why?” she asked, gently.
“Because I shall ever have before my mind what I have lost. Until
now existence has been tolerable, because I have tried to fill it with
bitter thoughts of you. In my own mind a hundred times a day I have
called you treacherous, false, cruel, and now my angel stands in her
place again, the truest and dearest of women, the woman I have
loved, and who has loved me! Hermione, my life will be so hard to
bear that, if it please Heaven, I could fain die standing here before
you now.”
“Brave men do not seek refuge in death,” she replied, “rather in
active duties of life.”
“Some men. You see, I have thrown my whole existence on one
stake; that stake was you, and I have lost you! Now I have to gather
up the broken threads of my life and do with them as best I can.”
She was weeping silently. He saw the teardrops falling, and a
mad impulse seized him to clasp her in his arms and kiss them
away. That he trampled the impulse under foot showed how dearly
he loved her.
“I am glad that we have met. Once more the sun of pure
womanhood shines for me. While I thought you false, Hermione, all
heaven and earth seemed false, too. But there is one thing more—
you may speak freely to me, Hermione; it is but as though one or the
other of us was dying—was there no truth in the rumor that you were
engaged to Kenelm Eyrle?”
“No; none. Mr. Eyrle has never loved or cared for me in his life.”
“Clarice believed it,” he said, musingly, and the pale face before
him grew whiter.
“She was deceived,” said Lady Hermione, briefly; “and now,
Ronald, it seems to me that we must say farewell; it must be for the
last time. We cannot meet as friends. Honor is dearer than life to
both of us; therefore, we must not meet again.”
“Oh, my lost love,” he moaned, stretching out his hands to her,
“how shall I bear it?”
She went up to him, and there was an expression of pity and love
on her face that made it divine. She took both his hands in her own
and held them there.
“You will be brave and true to yourself, Ronald. Do not let me
have the smart all my life long of knowing that love for me has led
you further from heaven; let it, rather, take you nearer. I have some
quaint thoughts, and one is that in another world God makes our
lives complete. Perhaps there, in that land where the gates are of
jasper and the walls of pearl, we may be together—who knows?
Looking to that time, we will forget the darkness and sorrow of this.”
He said to himself, bitterly, that such thoughts might comfort
angels and women; they brought no consolation to him.
“You must remember Clarice,” she pleaded; “Clarice, who loves
you so well.”
“I remember all. Hermione, if I send for you when I am dying,
should it be soon or should it be in twenty years, you will come to
me?”
“Yes,” she replied, with a deep-drawn, bitter sob. “I will come,
Ronald. Now, farewell.”
She was pure and innocent as the white doves that fed from her
hand. She saw no wrong in bending her sweet, sad face over him for
that last, most sorrowful embrace.
Once more his lips touched hers, but the chill upon them was the
chill of death.
“Good-by, my love, my dear, lost love, good-by,” he said, and the
words died away in a moan. Another minute and she had passed out
of sight.
When the hour of death came it was not so bitter for him as that
in which Hermione Lorriston passed out of his sight. He flung himself
on the ground, praying the skies might fall and cover him; that he
might never rise to meet the sunlight again.
From that day he was a changed man; he felt it and knew it
himself. The quiet, resigned content for which he had been trying so
hard was further from him than ever. The resignation arriving from
philosophy had forsaken him. Night and day he brooded over the
one idea that she had loved him, and he had lost her. Day and night
he pondered over the mystery of that letter.
But for his wife’s sake he would have made the whole matter
public and would have insisted on having it thoroughly sifted; but a
“still, small voice” pleaded for Clarice. It would be so hard for her to
see and know that his thoughts were still all of the past.
That did not prevent him from making a private investigation of
the matter. On the first day that he saw Conyers, the groom, he
called him.
“I want you,” he said. “There are some questions I wish to ask
you that, if you answer truthfully, will be of inestimable benefit to me;
if you answer them falsely, I shall be still further deceived. Perhaps
experience has embittered me; I have little faith left in man’s honesty.
I will buy your truth, Conyers, if you swear to me, on your oath, to
say nothing but what is perfectly, strictly correct. I will give you ten
pounds, and, should you be able to discover that which I wish to
know, I will hereafter give you fifty.”
Conyers was an honest man, and Sir Ronald’s words hurt him
more than he cared to own.
“If you offered me twice fifty pounds, Sir Ronald, to tell a willful
lie, I would not do it for you or for any one else. You can please
yourself about believing whether I tell you the truth or not.”
His bluntness did not displease the master of Aldenmere, who
looked at the groom’s face with a grim smile.
“If ever the world does to you what it has done to me,” he said,
quietly, “you will either doubt your own sanity or the truth of your
fellowmen. Come out here a few minutes; I want to talk to you.”
And the groom, laying down the work on which he was engaged,
followed his master out of the stable.
CHAPTER XXV.
THE MYSTERY UNSOLVED.

“Sit down, Conyers,” said Sir Ronald, pointing to an old wooden


bench. “I want you to carry your memory back to three years ago.”
“I can do that, Sir Ronald,” he replied; “my memory is a good
one.”
“Three years ago I called you and gave you a letter to take to
Leeholme Park; it was for Lady Hermione Lorriston, and you
promised me to place it in her own hands.”
“I remember perfectly, Sir Ronald.”
“Tell me what you did.”
“I drove straight to the hall and asked for her ladyship. She had
gone to Thringston with a party of guests staying in the house——”
“And then,” interrupted Sir Ronald, impatiently.
“I waited for her until I was afraid to wait any longer, and I asked
to see her maid. She is a young woman, sir, whom I have known for
many years; her name is Susan Fielding. She came to me, and I told
her you had intrusted me with a very particular letter, and I asked her
would she promise to give it to her ladyship. She said yes, and I
came away.”
“That is all you know about it?” asked Sir Ronald.
“Every word,” replied the man.
“Will you swear that you neither dropped it, changed it, or knew
its contents?”
There was genuine surprise in the honest face.
“I will swear, Sir Ronald; I will swear, as I hope to go to heaven,
that the letter was never for one moment out of my possession until I
placed it in Susan Fielding’s hand. I sat the whole time in the
servants’ hall. As for its contents, I never even thought of what they
were.”
“And, before God, that is the truth?”
“Before God I vow it,” said the groom, quickly.
“That letter never reached Lady Hermione Lorriston, Conyers;
and if you will help me find what became of it, I will reward you
richly.”
“I will do my best, Sir Ronald.” But the groom was evidently
puzzled, and his master saw it.
“I need not tell you there are many reasons why I object to having
it known that I am making any inquiries in the matter; but do you
think, Conyers, you could bring that maid, Susan Fielding, to see
me?”
“Yes; I can manage that, Sir Ronald; but unless you wish every
one to know it, you had better go to see her.”
“I cannot go to Leeholme,” he interrupted.
“There is no need, sir. If you wish to see Susan Fielding, I will ask
her to wait in the Thringston road, say to-morrow morning, and then
your interview will seem to have been accidental.”
“That will do. Ah! see, I am trusting you, despite all I had said
about honest men. Do not tell why I wish to see her; promise that.”
“I will not mention it; and mind, I should like you to be present as
well. If there has been any error we shall discover it then.”
That very evening Stephen Conyers went over to Leeholme and
contrived to see the lady’s maid. Pretty, coquettish Susan was
slightly agitated.
“What can Sir Ronald Alden want with me?” she asked. “Is May
Thorne leaving Lady Clarice?”
“I do not think so. You will be sure to be in the Thringston road,
Susan?”
“I shall not forget,” she replied; and the groom felt pretty sure that
feminine curiosity, if no other motive, would take her.
Imagine a long, winding high road, bordered on both sides with
tall trees, whose branches sometimes formed a shady arch.
Underneath the trees, walking impatiently, looking from right to left,
was Sir Ronald Alden. His handsome face was pale with agitation; it
seemed to him that they never would come.
Then, from between the clustering foliage, he saw two figures—
one was Stephen Conyers, the groom, the other the pretty,
coquettish Susan Fielding, Lady Hermione’s maid. His face flushed
hotly, for it struck him that for an Alden to hold an interview of the
kind with two servants was derogatory to dignity. Yet, unless he did
it, how was he ever to find out the truth?
Susan made her most respectful curtsy. The master of
Aldenmere was an important person, and that he should express a
wish to see her had filled her with wonder and curiosity.
They stood together under the great, spreading foliage, a curious
group.
“I have sent for you, Susan Fielding,” said Sir Ronald, “because I
wish to ask you some very important questions. I will deal with you
as with Conyers; I will pay you handsomely for the truth. If, by
anything you can tell me, you can throw even the least light upon a
dark mystery, I will reward you liberally.”
“I will do anything I can, Sir Ronald,” replied the maid, evidently
much mystified.
“I need only tell you both this much, that I had a most particular
letter to send to Lady Hermione Lorriston—a letter so important that
it seems idle to repeat it was a matter of life and death. That letter,
you remember, I sent by Stephen Conyers, the groom. He tells me,
Susan Fielding, that it was placed in your hands, and you promised
to give it to Lady Hermione. I will give you fifty pounds if you find out
for me what became of that letter.”
The maid looked at him in sheer wonder—it was not feigned, he
saw that plainly.
“I remember the letter perfectly well, Sir Ronald,” she said. “My
lady had it; I placed it on her toilet-table, and asked her afterward if
she had seen it, and she said, ‘Yes; it was all right.’”
“Remember,” interrupted Sir Ronald, “that I am trusting you both,
and that which I say to you must never be repeated. You have
touched the heart of the mystery, Susan Fielding. I believe you
placed the letter there. Now, listen! Before Lady Hermione opened it,
some one entered the room, opened the envelope, took from it my
letter and placed inside it a white rose! I will give you fifty pounds if
you find out for me who did this.”
“I do not think it could have been done, Sir Ronald.”
“I assure you it was. When Lady Hermione opened the envelope
it contained nothing but one white rose. The letter I had written, and
she had expected, was not there.”
If he had felt any doubt of Susan Fielding, the lingering look of
wonder on her face dispelled it. No woman, be she ever so clever,
could assume such an expression.
“I cannot think how it could be,” she said. “I remember the day so
well. There was a large party, and they all rode out together. My lady
returned and asked for some tea. I went downstairs to attend to it,
and she sat down in the music-room with three or four ladies; they
took tea there. Then she went to her room. I followed her. I said,
‘There is a packet on the table, my lady. Sir Ronald Alden’s groom
brought it.’ Lady Hermione smiled very indifferently. ‘I have seen it,’
she replied; and I do not remember, Sir Ronald, from that hour to
this, hearing the subject mentioned, except when Mr. Conyers spoke
of it the other day.”
“Then you can tell me nothing about it?” he asked, with a look of
keen disappointment.
“No; I cannot. I was away from Lady Hermione’s room half an
hour, not more, and it must have been changed in that time, if it were
changed at all.”
“You saw no one enter the room?”
“No, Sir Ronald; not that I remember.”
“I shall expect you to keep most perfect silence concerning this
inquiry,” said Sir Ronald. “I cannot make it public or I would.
Remember, that if you can find out anything which will bring the
mystery to light, I will give you, not fifty, but a hundred pounds.”
“I will do my best,” she replied; “but I have not much hope. If it
were done by any person in the house they took such precaution as
would insure its never being known.”
But as Sir Ronald walked away a peculiar expression flashed into
the woman’s face, one of wonder, surprise and pain.
“What is it?” asked the groom. “Do you remember anything?”
“No,” she replied; but her voice was peculiar, and during the
remainder of the walk home Susan Fielding spoke never a word.
CHAPTER XXVI.
AFTER NIGHT, MORNING.

From that time Sir Ronald Alden changed so completely that he


was hardly to be recognized as the same man. He ceased to
struggle for content; he said to himself that a curse was upon him,
and he must live under it while it pleased Heaven that he should live
at all; but the happiest moment that life held in store for him would be
the one that held death—the moment that would bring the woman he
loved to his side to look at him for the last time. He was young, and
life ran full, warm and rich in his veins, yet he would have gladly laid
it down to have brought her for only one moment to his side, so great
and passionate was his love for her.
Lady Clarice could not fail to notice the change. She comforted
herself by thinking that the Aldens were a strange race, not governed
by the same laws as other men, subject to moods and passions that
required indulgence. She never dreamed that he had met Lady
Hermione, and that his new sorrow was caused by the constant
smart of knowing that life might have been different for him.
“Ronald,” she said to him one day, “has life any interest for you?”
“No,” he replied; “I cannot, in truth, say that it has.”
Her face flushed warmly.
“Then, if I were you, I should be ashamed to say so. You are the
first Alden who has found life empty, I should imagine.”
“I did not say it was empty, Clarice; I merely say nothing in it
interests me.”
She knelt down by his side, and clasped her white hands round
his arm.

You might also like