Object Oriented Principles

Web page by Kevin Harris of Homer IL

Please contact Kevin Harris of Homer IL concerning this web site

Object Oriented Principles

Reference: Microsoft Virtual Academy: A Guide to Object-Oriented Practices by Bill Wagner and James Sturtevant.

Many languages played important roles in the evolution of Object-Oriented Programming (OOP). The languages: Simula, Smalltalk, C++, and Java are frequently cited as having a major impact on the development of OOP. C++ was designed to be a superset of C, so it is frequently described as an imperative language with object-oriented features. In fact many modern languages are considered to be multi-paradigm, such as Java which is considered to be object-oriented, imperative, structured (procedural), generic, reflective, and concurrent. Java fully supports object-oriented principles and its highly portable nature (Java virtual machine concept) makes it very popular. Microsoft developed C# in response to Java's popularity.

C# is a fully object-oriented language (for more details see OOP article on my Microsoft Developer website Object-Oriented Programming) which runs on the .NET environment. VB.NET was a complete rewrite of VB6 to make it a true object-oriented language which supports inheritance, polymorphism, and encapsulation. All the .NET languages are interoperable and share common concepts concerning OOP. The context and examples in this article all use the C# language.

Encapsulation


  • Encapsulation includes an information-hiding mechanism for restricting access to some of the object's components. Encapsulation hides the internal state of your object from direct access from outside code. This allows the internal implementation of the state to change at will, while presenting an interface that doesn't change. External code doesn't have access to the internal state of your object, so it can't alter it in an inconsistent manner that could break the way the object works.
  • C# offers the programmer a degree of control over what is hidden through the use of access modifiers. Access modifers are keywords in C# that declare the accessibility of a Class or a Class Member. The default access levels are:
    • class = internal
    • struct = internal
    • class members, struct members, nested classes and structs = private
    • interface members, enum members = always public (only)
    Keyword Applicable To Meaning
    public class, member Access is not restricted.
    protected member Access limited to the class and derived classes.
    internal class, member Access limited to the current assembly (.exe, .dll).
    protected internal member Access limited to current assembly and types derived from class.
    private class, member Access limited to the class.


Classes should be kept as small as possible and limit the number of public accessors. Classes should adhere to the Single Responsibility Principle and have a single objective. This corresponds to the first of the SOLID principles of object-oriented design:

  • S - Single Responsibility Principle - a class should have only a single responsibility (i.e. only one potential change in the software's specification should be able to affect the specification of the class).

  • O - Open/Closed Principle - software entities should be open for extension, but closed for modification.

  • L - Liskov Substitution Principle - objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.

  • I - Interface Segregation Principle - many client-specific interfaces are better than one general-purpose interface.

  • D - Dependency Inversion Principle - depend upon Abstractions. Do not depend upon concretions.

Examples of encapsulation were reviewed from the Microsoft GitHub repository for the following classes:

  1. Stringbuilder - hides complex unsafe code which is copies values in memory to be highly performant. Use Stringbuilder() for concatenating strings because strings are immutable in .NET.

  2. HashTable - hides complex hashing algorithms which evenly distribute values across the buckets. HashTable uses key/value pairs like the Dictionary structure. The newer Dictionary structure supports generics so is faster when working with value types (i.e. no boxing/unboxing converting value types to objects).

  3. ArrayList - a wrapper around an array that allows it to grow or shrink itself.

  4. return this; - returns the object itself. Is used support method chaining.

Inheritance


Inheritance enables the creation of new classes which reuse, extend, and modify the behavior define in other classes. The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. C# and Java support single inheritance, meaning a derived class can have only one base class. However, inheritance is transitive. If Class C is derived from Class B, and Class B is derived from Class A, then Class C inherits the members declared in Class B and Class A. The software reuse provided by inheritance can result in a smaller code base with small components which are easier to test and are more immune to breaking changes during modifications.

Inheritance should be designed based upon common behaviors, where as common storage is not necessarily important for good inheritance. Behaviors are defined in the base class and depending upon how they are defined, the derived class can use the behavior as defined, or may be able to re-implement the behavior, or may be required to implement the behavior. Member declarations which affect inheritance are:

  1. Protected - is an access modifier which allows the members to be accessed in derived classes, as well as the current class.

  2. Virtual - the virtual keyword allows it to be overridden in the derived class. A virtual inherited member can be overridden in a derived class by including a declaration that uses the override modifier. It is an error to use the virtual modifier on a static member.

  3. Abstract - the abstract modifier indicates the code is missing and must be declared in the derived class.

  4. Sealed - the sealed modifier on a class prevents other classes from inheriting from it. You can also use the sealed modifier on a method or property that overrides a virtual method or property in a base class. This enables you to allow classes to derive from your class and prevent them from overriding specific virtual methods or properties.

The Liskov Substitution Principle (LSP) concerns behavioral subtyping which has been applied to classes in OOP. The principle, as applied to classes, requires a derived class be able to be substituted for the base class, when only the capabilities of the base class are used. So if class S is derived from class T, then you should be able to substitute class S any place T is used, as long as you are treating S like the base class.

An indicator of an LSP violation is when down casting a class causes erroneous results or an exception. Adhering to LSP is desirable, but not always possible in the real world. There are examples of LSP violations in the .NET base class library (BCL) which involve down casting issues for which the is no apparent resolution. Examples of those LSP violations in the BCL occur when dealing with collections. Inappropriate inheritance hierarchy which violate LSP should be considered for refactoring using "is-a" relationships, but there are cases where LSP may not always be achievable.

The classic example of an LSP violation is a Square derived from a Rectangle class. If you expose the height and width function of the Rectangle to the Square, then you be able to have different length sides available on the base class, which is not permitted on the derived class.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Violation of Likov's Substitution Principle
class Rectangle
{
	protected int m_width;
	protected int m_height;

	public void setWidth(int width){
		m_width = width;
	}

	public void setHeight(int height){
		m_height = height;
	}


	public int getWidth(){
		return m_width;
	}

	public int getHeight(){
		return m_height;
	}

	public int getArea(){
		return m_width * m_height;
	}	
}

class Square extends Rectangle 
{
	public void setWidth(int width){
		m_width = width;
		m_height = width;
	}

	public void setHeight(int height){
		m_width = height;
		m_height = height;
	}

}

class LspTest
{
	private static Rectangle getNewRectangle()
	{
		// it can be an object returned by some factory ... 
		return new Square();
	}

	public static void main (String args[])
	{
		Rectangle r = LspTest.getNewRectangle();
        
		r.setWidth(5);
		r.setHeight(10);
		// user knows that r it's a rectangle. 
		// It assumes that he's able to set the width and height as for the base class

		System.out.println(r.getArea());
		// now he's surprised to see that the area is 100 instead of 50.
	}
}


The Liskov Substitution Principle helps to guarantee inclusion polymorphism (a.k.a. subtype polymorphism) for class hierarchies in OOP. Other types of polymorphism exist languages, such as support for method overloading (Ad hoc Polymorphism) or code which can be written without mention of any specific types (Parametric Polymorphism) which is also referred to as Generics.

  1. Ad hoc Polymorphism - occurs when a method denotes different and potentially heterogeneous implementations. Supported in many languages through method overloading.

  2. Parametric Polymorphism - occurs when code is written without mention of any specific type and can be used transparently with any number of different types. In OOP, this is often referred to as generics or generic programming.

  3. Inclusion Polymorphism - occurs when a class hierarchy adheres to LSP.


Interfaces


An Interface in C# (and Java) is a collection of abstract methods (i.e. not implemented) and final fields (e.g. constants) which is similar to a class. In C#, you can only derive from one base class, but you can implement multiple interfaces. The interface provides the method signatures without any implementation of the method. The class which implements the interface must implement all of the methods in the interface (or be an abstract class).

All methods in an interface are assumed public and abstract. Interfaces can extend other interfaces, similar to how a class can extend another class.
The C# Programming Guide defines an interface:

An interface contains definitions for a group of related functionalities that a class or a struct can implement.
By using interfaces, you can, for example, include behavior from multiple sources in a class. That capability is important in C# because the language doesn't support multiple inheritance of classes. In addition, you must use an interface if you want to simulate inheritance for structs, because they can't actually inherit from another struct or class.

and provides this summary of an interface's properties.

  • An interface is like an abstract base class. Any class or struct that implements the interface must implement all its members.
  • An interface can't be instantiated directly. Its members are implemented by any class or struct that implements the interface.
  • Interfaces can contain events, indexers, methods, and properties.
  • Interfaces contain no implementation of methods.
  • A class or struct can implement multiple interfaces. A class can inherit a base class and also implement one or more interfaces.

I liked this example of an interface submitted by Danny Chen on Stack Overflow:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
interface IFlyable
{
    void Fly();
}

class Bird : IFlyable
{
    public void Fly() { }
}

class Plane : IFlyable
{
    public void Fly() { }
}

List<IFlyable> things = GetBirdInstancesAndPlaneInstancesMixed();
foreach(IFlyable item in things)
{
   item.Fly();
}



Abstract Classes


Abstract classes cannot be instantiated. Abstract classes are designed to be base classes. Abstract base classes can provide some shared implementation, which is a distinguishing difference from Contracts. When trying to decide whether to use an Abstract base class or a Contract, consider the amount of shared implementation which will be available. Another reason for using an abstract base class instead of an interface is to force the derived class from using another base class, as in C# a class can inherit from only one base class. Choosing between an abstract base class and an interface can communicate intended usage to other developers. This helps guide the user's of your classes to use them successfully, or as Rico Mariani coined the phrase, "to fall into the pit of success", as opposed to success being a far off summit with a difficult path to traverse.

Note the abstract modifier is used in C# to indicate things are missing, or have an incomplete implementation. Besides being used with classes, it can also be used with methods, properties, indexers, and events. In VB an abstract class is denoted with the MustInherit keyword.

Abstract classes are used when you want to make base classes, but you do not want anyone to create objects from these classes. Abstract classes can contain full implementation or partial implementation of the methods. Any method which is not implemented in the abstract base class must be implemented in the derived class in order to compile. Methods which are not implemented in the abstract class will themselves be marked as abstract. Methods marked as virtual will provide an implementation, but that implementation can be overridden in the derived class. The overridden method will have the same signature as the virtual class, but the run time will know to call the overridden method, supporting the polymorphic behavior.

Abstract base classes can be used to define a common implementation. Consider marking base class as abstract when they are developed. You can remove abstract later if needed, but it is hard to make them abstract once someone start instantiating them in their code.

Examples of abstract base classes in the BCL include the Controller class. You can not create an instance of the Controller class, but you must derive from the Controller class to use it. The base classes should model using the "is-a" method correctly and the class hierarchy should not be too deep. Keeping the class hierarchy more flat makes it easier to work with.

Abstract classes are designed to be base classes, so they can not be marked as Sealed (prevents inheritance of the class). Some of the restrictions on abstract base classes include the following:

  • An abstract class cannot be instantiated.

  • An abstract class cannot be a sealed class because the sealed modifier prevents a class from being inherited and the abstract modifier requires a class to be inherited.

  • If an abstract class contains abstract methods, they must be implemented in the derived class in order to compile. The implementations should be complete and should not contain NotImplemented exceptions.

In the following example the abstract class is declared with one implemented method and three unimplemented methods:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
abstract class WashingMachine
{
   public WashingMachine()
   {
      // Code to initialize the class goes here.
   }

   abstract public void Wash();
   abstract public void Rinse(int loadSize);
   abstract public long Spin(int speed);
}


Generics



Generics allow a class, method, or interface to specify the types of arguments or return values at the time of instantiation.

Generics provides software reuse through parametric polymorphism. It also provide type safety and avoids run-time errors which can occur when the wrong type is used. An analogous situation is having a method which works with strings. You want the method to also work with integers so you copy and paste the method and change all occurrences of string to int. With generics the compiler does this for you and you only have to maintain one copy of the method. When executing the run-time ensure the correct types are used. When using generics, the compiler and run-time work together to ensure the correct types are always used.

Generics provides type safety by having the system determine the proper type to use in the various situations. When using inheritance to provide inclusive polymorphism a class is downcast and used as if it was a derived class. This can require code to check the type of the object to ensure it does not use members of the child class which are not available to the parent class. An easier way to obtain the same results is to create constraints on the generic type parameters.

Constraints on Type Parameters are used to control the degree to which the type parameter is generic. The degree to which a type parameter can be generic varies across a continuum ranging from system.Object (which is the ultimate base class for all objects in .NET) to a single specific type. Constraints can define the following requirements for a type parameter:

  • The interface(s) the type must implement.

  • The base class the type must inherit.

  • If it must use a parameterless constructor.

  • Whether it is a class or a struct (they are mutually exclusive).

When you use the generic T type parameter, the only thing associated with the type is the members of system.Object. Constraints add other required behaviors to the generic type parameter. Constraints should be kept to a minimum, but should be used to having to do type checking in the generic algorithm. If you find you specifying a lot of constraints, you may need to rethink the appropriateness of the generic type because you could be adding unnecessary complexity to the code. In this case maybe a specific data type would be better than a generic type.

Generics were introduced in .NET 2.0 and are currently used widely in the base class library (BCL) of the framework. For backwards compatibility some methods have both generic and non-generic versions, but new development should consider using the generic versions. Generics are used in BCL methods such as LINQ queries and the Task method for performing asynchronous work. Generics are used in BCL interfaces such as IComparable and IEquatable. Generic classes contain a generic parameter for some fields or properties in the class. Collections in .NET widely use generics such as the List class.

The MSDN C# programming documentation contains a comprehensive article on generics called An Introduction to C# Generics The following example was pulled from that article.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class LinkedList<K,T> where K : IComparable
{
   T Find(K key)
   {
      Node<K,T> current = m_Head;
      while(current.NextNode != null)
      {
         if(current.Key.CompareTo(key) == 0)
            
            break;
         else      
            
            current = current.NextNode;
      }
      return current.Item; 
   }
   //Rest of the implementation 
}


Note: downcast - is the act of casting a reference of a base class to one of its derived classes. You are casting down the class hierarchy from a more general class to a more specific class.


Delegates, Events, and Lambda Expressions


Delegates are one of the five types included with .NET: class, structure, interface, enumeration, and delegate. Delegates are variables, that instead of storing data, store the reference to a method which has a declaration which matches the signature specified in the delegate .

Delegates can be considered as method pointers which allow methods to be passed to other methods. They are commonly used as call back functions in asynchronous programming and with events in event programming. Delegates define a method signature and which represents any method which matches the defined signature. The actual method used can be be assigned at run-time instead of compile-time. Delegates are also used extensively in LINQ methods and are also critical to functional programming which passes functions around just as data is passed around in code.

Lambda Expressions are a shorthand syntax which can be used to define delegate instances. Bob Tabor likes to call them mini-methods which is a good analogy. See C# Fundamentals for Absolute Beginners on Channel 9. Lambda Expressions where introduced in C# 3.0 (released 11/19/2007) and allows you to write an anonymous method in the same place as you use it, which is very convenient for delegates. This saves you from having to declare and write a named method to be used with the delegate. See Lambda Expressions (C# Programming Guide) for more on lambda expressions. Note: As this writing C# 6.0 is the most recent release (released in 7/20/2015).

Events are delegates with a specific declaration pattern which is used by convention. The declaration pattern for an event contains a void return value and contains two arguments. The first argument is object which raised the event and the second argument is a type derived from EventArgs which is used to pass information about the event. (i.e. argument pattern is (sender, event args). The compiler will not enforce this declaration pattern, but there is a lot of software which will assume this pattern is used. Another convention frequently used is to prefix the name of the event handler with "On" (i.e. OnClick).

Delegates

Delegates provide a lightweight form of polymorphism which allows any method to be used as long as its signature matches the signature specified in the delegate. The concise syntax for creating and using delegates may be more appropriate than other ways of creating polymorphism such as contracts or abstract base classes. Delegates are especially useful where a method is needed for just a single use, such as in the Where LINQ method. If you had to define a method every time you wanted to create a Where clause it would be an excessive amount of coding and harder to read. However there are cases where abstract base classes and interfaces are more appropriate than delegates. Consider what the BCL would be like if there were no base classes. So choosing between delegates, interfaces, and abstract base classes is an important design decision.

A delegate declaration specifies the signature of a method using the delegate keyword. This provides a loose coupling between the caller and the called method. Lambda expressions can be used with delegates to concisely, and anonymously, define the functionality to be performed without having to create a named method. This reduces the number of method names which need to be created.

Examples of delegates in the BCL are the Lazy and Task classes. The Lazy class takes a generic parameter type and allows the functionality to be executed on when it is actually needed. The Task class also takes a generic type parameter and can execute a task asynchronously, such as when making a network call, or queue a task to run on another thread (i.e. Task.Run()).

1
2
  // Delegate Declaration
  public delegate void MyDelegate();


The following is an example of declaring and using a delegate which I found on Stack Overflow:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using MyLibrary;

 

namespace DelegateApp {

 

  /// <summary>

  /// A class to define a person

  /// </summary>

  public class Person {

    public string Name { get; set; }

    public int Age { get; set; }

  }

 

  class Program {

    //Our delegate

    public delegate bool FilterDelegate(Person p);

 

    static void Main(string[] args) {

 

      //Create 4 Person objects

      Person p1 = new Person() { Name = "John", Age = 41 };

      Person p2 = new Person() { Name = "Jane", Age = 69 };

      Person p3 = new Person() { Name = "Jake", Age = 12 };

      Person p4 = new Person() { Name = "Jessie", Age = 25 };

 

      //Create a list of Person objects and fill it

      List<Person> people = new List<Person>() { p1, p2, p3, p4 };

      DisplayPeople("Children:", people, IsChild);

     DisplayPeople("Adults:", people, IsAdult);

      DisplayPeople("Seniors:", people, IsSenior);

 

      Console.Read();

    }

 

    /// <summary>

    /// A method to filter out the people you need

    /// </summary>

    /// <param name="people">A list of people</param>

    /// <param name="filter">A filter</param>

    /// <returns>A filtered list</returns>

    static void DisplayPeople(string title, List<Person> people, FilterDelegate filter) {

      Console.WriteLine(title);

 

      foreach (Person p in people) {

        if (filter(p)) {

          Console.WriteLine("{0}, {1} years old", p.Name, p.Age);

        }

      }

 

      Console.Write("\n\n");

    }

 

    //==========FILTERS===================

    static bool IsChild(Person p) {

      return p.Age <= 18;

    }

 

    static bool IsAdult(Person p) {

      return p.Age >= 18;

    }

 

    static bool IsSenior(Person p) {

      return p.Age >= 65;

    }

  }

}



Events

Events are used to notify external code when some action of interest happens, such a button being clicked. The external code subscribes to the event in order to be notified when the action occurs. Events can be subscribed to by one or more subscribers, but there are no subscribers then the event will not be raised. When a public event is published, there are no assumptions about the type of code which will process the event. That is, there is no interface or base class required for the code which will process the event. This creates a loose-coupling between the code which raises the event and the code which handles the event.

The most familiar use of events is with graphical interfaces. The controls of the interface raise an event when the control is used and the event handler performs the desired logic which is coded to be associated with the control action. However events can also be used in other situations such as monitoring state change, or logging error. For example events may be used to notify the user when a process is 90% completed, or to create log messages when errors occur. For more information see the Events Tutorial on MSDN.

When working with graphical interfaces the programmer is typically only coding the event handlers for events which are already defined, such as those events in the Window object. In the case of recording state changes or logging error messages, the programmer also creates the events. Below is a simple example of creating and defining and event.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;

namespace EventExample2

{

 

    public class TimeOfTick : EventArgs

    {

        private DateTime TimeNow;

        public DateTime Time

        {

            set

            {

                TimeNow = value;

            }

            get

            {

                return this.TimeNow;

            }

        }

    }

    public class Clock

    {

        public event TickHandler Tick;

        public delegate void TickHandler(Clock c, TimeOfTick e);

        public void Start()

        {

            while (true)

            {

                System.Threading.Thread.Sleep(3000);

               if (Tick != null)

                {

                    TimeOfTick TOT = new TimeOfTick();

                    TOT.Time = DateTime.Now;

                    Tick(this, TOT);

                }

            }

        }

    }

    public class Listener

    {

        public void Subscribe(Clock c)

        {

            c.Tick += new Clock.TickHandler(HeardIt);

        }

        private void HeardIt(Clock m, TimeOfTick e)

        {

            System.Console.WriteLine("HEARD IT AT {0}", e.Time);

       }

 

    }

    class Test

    {

        static void Main()

        {

            Clock c = new Clock();

            Listener l = new Listener();

            l.Subscribe(c);

            c.Start();

        }

    }

}


Functional Concepts


Pure functions take input and return an output which is solely dependent upon the input. Pure functions have no side-effects, meaning they do not unintentionally modify data residing in a higher scope. An example of an occurrence of a side-effect is when a class, which contains data, is concurrently accessed from different threads. Functions can not cause side effects as their output is entirely dependent upon their input. Eliminating side effects is one of the primary motivations for using functional programming. This is particularly useful when working with multiple threads or asynchronous code.

Pure functions are idempotent, meaning no matter how may times they are called, the effect is the same. That is, there is no observable difference regardless how many times the function is called. This is possible because they maintain no state. This makes them easy to run in parallel as they are inherently thread-safe. They are also easier to test because of their stateless nature. The functional style of programming is currently in vogue and emphasis is placed on striving for statelessness in both functions and methods. Functional programming is a good way to get things coupled together a run time with a lot less static binding and a lot less structure on the type system.

Functional programming languages use a declarative approach to programming which uses expressions to evaluate mathematical functions and avoids changing-state and mutable data. Functional programming languages treat functions as first class citizens, which means they have no restrictions on their use. In which case functions can be passed around just like data. F# is a .NET language which supports functional programming. In C# 3.0 facilities where added to the language to facilitate a functional style of programming.

First-order functions take data and input and return data as output. Higher-order functions can take as input, or return as output, other functions. JavaScript made the use of higher-order functions populate with the use of their callback functions. JavaScript and Python had first class functions since their creation, while other languages, such as C++, VB, and C# had first-class functions introduced after they were created. In .NET, the LINQ library contains numerous examples of functional programming in the method syntax where various methods are chained together. In which case the functions are encoded as delegates, typically using lambda expression syntax. The LINQ methods show how functions focus on "How" data is to be processed, where the developer specifies "What" data is to be processed. For example a developer specifies what data is to be sorted and the LINQ functions specify how the data will be sorted.

Functions have been used in programming for many years. But typically the are used in an manner that uses imperative control structures where this function is called and latter, if a condition is true, another function might get called. Functional programming compose algorithms as a series of function calls. Functional programming creates a pipeline where one function feeds into another function, and so on. Functional designs roll through a series of functions to compose a larger algorithm.

Functions can be found in Extension Methods which are external methods which act as if they are internal methods of a class. Extension methods must be in a static class and the method must also be static. Another requirement of extension methods is the first argument must be the "this" keyword to pass in the object. Below is an example of an extension method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}
Error | ASP.NET Developer

Error

Error message

  • Warning: Cannot modify header information - headers already sent by (output started at /srv/disk9/1218369/www/kcshadow.net/aspnet/includes/common.inc:2748) in drupal_send_headers() (line 1232 of /srv/disk9/1218369/www/kcshadow.net/aspnet/includes/bootstrap.inc).
  • PDOException: SQLSTATE[42000]: Syntax error or access violation: 1142 INSERT command denied to user '1218369_b2cf'@'185.176.40.58' for table 'watchdog': INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => 0 [:db_insert_placeholder_1] => cron [:db_insert_placeholder_2] => Attempting to re-run cron while it is already running. [:db_insert_placeholder_3] => a:0:{} [:db_insert_placeholder_4] => 4 [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => http://www.kcshadow.net/aspnet/?q=node/114 [:db_insert_placeholder_7] => [:db_insert_placeholder_8] => 54.80.87.62 [:db_insert_placeholder_9] => 1534852070 ) in dblog_watchdog() (line 160 of /srv/disk9/1218369/www/kcshadow.net/aspnet/modules/dblog/dblog.module).
The website encountered an unexpected error. Please try again later.