Advanced C# language features

The content and code of this article is referenced from book Pro C#5.0 and the .NET 4.5 Framework by Apress. The intention of the writing is to review the konwledge and gain better understanding of the .net framework. 

1. Indexer method

As a developer, we are all familar with the process of accessing array using index opeator []. The .net framework provides the capability to design custom classes and structures that may be indexed just like a standard array, by defining indexer method.

An indexer is represented as a slightly modified c# property definition.

 1    class PersonCollection : IEnumerable
 2     {
 3         private ArrayList arPeople = new ArrayList();
 4
 5         //custom indexer for this class
 6         public Person this[int index]
 7         {
 8             get { return (Person) arPeople[index]; }
 9             set { arPeople.Insert(index, value);}
10         }
11
12         public IEnumerator GetEnumerator()
13         {
14             throw new NotImplementedException();
15         }
16     }

Apart from using this keyword, the indexer looks like just like any other c# property declaration.  In addition, do remember that generic types give you this very functionality out of the box.

1      private static void UserGenericList()
2         {
3             List<Person> myPeople = new List<Person>();
4             myPeople.Add(new Person{FirstName = "person1", LastName = "test", Age = 20});
5             myPeople.Add(new Person { FirstName = "person2", LastName = "test", Age = 22 });
6
7             //using indexer method
8             myPeople[0] = new Person() {FirstName = "Jason", LastName = "test", Age = 32};
9         }

1.1 Indexing data using string value

In the previous example, we defined an indexer method that allowed the caller to identify subitems using a numerical value. However, this is not a requirement for an indexer method, we can use string value as well.

 1     class PersonCollection : IEnumerable
 2     {
 3         private Dictionary<string, Person> listPeople = new Dictionary<string, Person>();
 4
 5
 6         //custom indexer for this class
 7         public Person this[string name]
 8         {
 9             get { return (Person) listPeople[name]; }
10             set { listPeople[name] = value; }
11         }
12
13         public IEnumerator GetEnumerator()
14         {
15             return listPeople.GetEnumerator();
16         }
17     }

Again, if you were to use the generic Dictionary<TKey, TValue> type directly, you‘d gain the indexer method functionality out of the box.

1.2 Overloading indexer method

Understand that indexer methods may be overloaded on a single class or structure.

1.3 Indexers with multiple dimensions

You may also create an indexer method that takes multiple parameters.

1         public int this[int row, int column]
2         {
3             get { return myarray[row, column]; }
4             set { myarray[row, column] = value; }
5         }

1.4 Indexer on interface type

Indexers can be defined on a given .net interface type to allow supporting types to provide a custom implementation.

    interface IStringContainer
    {
        string this[int index] { get; set;}
    }

Any class or structure that implements this interface must now support a read/write indexer that manipulates subitems using a numerical value.

2. Operator overloading

In c#, it gives you the capability to build custom classes and structures that also respond uniquely to the same set of basic tokens.

2.1 overloading binary operator

c# provides the operator keyword, which you can use only in conjunction with the static keyword.  

 1     public class Point
 2     {
 3         public int X { get; set; }
 4         public int Y { get; set; }
 5
 6         //overloaded operator +
 7         public static Point operator + (Point p1, Point p2)
 8         {
 9             return new Point(p1.X + p2.X, p1.Y + p2.Y);
10         }
11
12         public static Point operator -(Point p1, Point p2)
13         {
14             return new Point(p1.X - p2.X, p1.Y - p2.Y);
15         }
16
17         public Point(int xPos, int yPos)
18         {
19             X = xPos;
20             Y = xPos;
21         }
22
23     }

When you are overloading a binary operator, you are not required to pass in two parameters of the same type.

1 //overloaded operator with different types of parameters
2         public static Point operator + (Point p1, int change)
3         {
4             return new Point(p1.X + change, p1.Y + change);
5         }

2.2 overloading Unary operator

C# also allows you to overload various unary operators, such as ++ and --. When you overload a unary operator, you also must use the static keyword with the operator keywrod; In this case, you simple pass in a single parameter that is the same type as the defining class/structure.

        public static Point operator ++(Point p1)
        {
            return new Point(p1.X + 1, p1.Y + 1);
        }

2.3 Overloading equality operators

System.object.Equals() can be overridden to perform value-based (rather that reference-based) comparisons between reference types.

 1       //overload the == and !=
 2         public static bool operator ==(Point p1, Point p2)
 3         {
 4             return p1.Equals(p2);
 5         }
 6
 7         public static bool operator !=(Point p1, Point p2)
 8         {
 9             return !p1.Equals(p2);
10         }

keep in mind that, C# demands that if you override the == operator, you must also override the != opertaor.

2.4 Overloading comparison operator

In previous chapter, we learned how to implement the IComparable interface in order to compare the relationship between two objects. You can also overload the comparison operator for the same class.

        public static bool operator <(Point p1, Point p2)
        {
            return (p1.CompareTo(p2) < 0);
        }

        public static bool operator >(Point p1, Point p2)
        {
            return (p1.CompareTo(p2) > 0);
        }

3. Custom type conversion

3.1 Conversion recap

In terms of the intrinsic numerical types (int, float), an explicit conversion is required when you attempt to store a larger value into a smaller container. Implicit conversion happens automatically when you attempt to place a smaller type in a destination type that will not result in loss of data.

        static void Main(string[] args)
        {
            int a = 123;
            long b = a; //implicit
            int c = (int) b; //explicit
        }

c# also allows you to cast up and down the class hierarchy. A derived can always be implicitly cast to a base type. However, if you want o store a base class type in a derived variable, you must perform an explicit cast.

What if you have two class types with no common parent that requires conversion?

3.2 Custom conversion routines

C# provides two keywords, explicit and implicit, that you can use to control how your types respond during an attempted conversion.

 1     public class Square
 2     {
 3         public int Width { get; set; }
 4
 5         public static explicit operator Square(int sideWidth)
 6         {
 7             return new Square{Width = sideWidth};
 8         }
 9
10         public static explicit operator int(Square s)
11         {
12             return s.Width;
13         }
14     }
 1     public class Rectangle
 2     {
 3         public int Width { get; set; }
 4         public int Height { get; set; }
 5
 6         public static implicit operator Rectangle(Square s)
 7         {
 8             return new Rectangle{Height = s.Width, Width = 2 * s.Width};
 9         }
10     }

4. Extension Methods

.net 3.5 introduced the conecpt of extension methods, which allows you to add new methods or properties to a class or structure, without modifying the original type in any direct manner.

4.1 Define extension method

When you define extension method, the first restriction is that they must be defined within a static class, and, therefore, each extension method must be declared with the static keyword. Secondly, all extension methods are marked as such by using this keyword as a modifier on the first parameter of the method.

    public static class MyExtensions
    {
        public static void DisplayDefiningAssembly(this object obj)
        {
            Console.WriteLine ("{0} lives here :=> {1}\n", obj.GetType ().Name, Assembly.GetAssembly (obj.GetType ()).GetName ().Name);
        }
    }

Invoke the extension method.

        public static void Main (string[] args)
        {
            int myInt = 2324;
            MyExtensions.DisplayDefiningAssembly (myInt); //calling extension method
        }

4.2 importing extension method

If the namespace is different from the namespace using the extension methods, you will need to make use of the expected C# using keyword. It‘s common practise to not only isolate extension methods into a dedicated .net namespace, but into a dedicated class library.

4.3 Extending types implementing specific interfaces

It is possible to define an extension method that can only extend a class or structure that implements the correct interface.

        public static void PrintData(this System.Collections.IEnumerable iterator)
        {
            foreach (var item in iterator) {
                Console.WriteLine (item);
            }
        }

And now, the extension can be invoked by any class that implements IEnumerable.

       public static void Main (string[] args)
        {
            string[] data = { "test1", "test2", "test3" }; //array does implement IEnumerable
            MyExtensions.PrintData (data);
        }

5. Working with anonymous type

As OO developer, we all know the benefits of defining classes. However, there are other times when you would like to define a class simply to model a set of data without any methods or events.

5.1 Defining anonymous type

When you define anonymous type, you do so by making use of the var keyword in conjunction with object initialization syntax.

        static void BuildType()
        {
            var person = new {Name = "jason", Age = 25};  //anonymous type

            Console.WriteLine ("Person name is {0}", person.Name);
        }

5.2 Internal representation of anonymous type

All anonymous type are automatically derived from System.Object, and therefore, support each of the members provided by this base class.

5.3 Anonymous types containing anonymous type

        static void BuildType()
        {
            var purchaseItem = new {
                TimeBought = DateTime.Now,
                ItemBought = new {Make = "make1", Color= "Red"},
                Price = 12
            };
        }
时间: 2024-12-29 16:04:08

Advanced C# language features的相关文章

Best 5 C# 6.0 Language Features

Best 5 C# 6.0 Language Features # Expression Bodied Methods How many times have you had to write a method just for one line of code? Now, with C# 6 you can simply create an expression bodied member with only the expression and without the curly brace

Chapter3 New Language Features

ch3.1   new c++11  language features 3.1.1  important minor syntax changes space in template expression                vector< list<int> >      // ok in each c++ version                vector< list<int>>      // ok since c++11 null

CME 292 Lecture 1 Language Features

Numeric arrays Introduction High-level language for technical computing Integrates computation, visualization, and programming Sophisticated data structures, editing and debugging tools, object-oriented programing MATrix LABoratory (MATLAB) Highly op

openjdk源码阅读导航

转自:http://rednaxelafx.iteye.com/blog/1549577 这是链接帖.主体内容都在各链接中. 怕放草稿箱里过会儿又坑掉了,总之先发出来再说…回头再慢慢补充内容. 先把ItEye网站上的信息聚合起来. 近期提问帖: 阅读openjdk源代码 如何来看OpenJDK源码 如何分析OpenJDK中JVM的实现 一个个回复太麻烦了,合在一块儿写这么一篇. ================ 前言 我的VM帖的索引 高级语言虚拟机(HLLVM)群组 新浪微群“JVM源码阅读活

转-OpenJDK源码阅读导航跟编译

OpenJDK源码阅读导航 OpenJDK源码阅读导航 博客分类: Virtual Machine HotSpot VM Java OpenJDK openjdk 这是链接帖.主体内容都在各链接中. 怕放草稿箱里过会儿又坑掉了,总之先发出来再说…回头再慢慢补充内容. 先把ItEye网站上的信息聚合起来. 近期提问帖: 阅读openjdk源代码 如何来看OpenJDK源码 如何分析OpenJDK中JVM的实现 一个个回复太麻烦了,合在一块儿写这么一篇. ================ 前言 我的

斯坦福CS课程列表

http://exploredegrees.stanford.edu/coursedescriptions/cs/ CS 101. Introduction to Computing Principles. 3-5 Units. Introduces the essential ideas of computing: data representation, algorithms, programming "code", computer hardware, networking, s

Delphi Language Overview

Delphi is a high-level, compiled, strongly typed language that supports structured and object-oriented design. Based on Object Pascal, its benefits include easy-to-read code, quick compilation, and the use of multiple unit files for modular programmi

Lua 架构 The Lua Architecture

转载自:http://magicpanda.net/2010/10/lua%E6%9E%B6%E6%9E%84%E6%96%87%E6%A1%A3/ Lua架构文档(翻译) 十 102010 前段时间翻译了lua官方关于lua5架构设计的一份文档,现在分享给大家. 注意:所有版权都归lua官方所有,本人仅将其翻译为中文,以方便中文阅读者.翻译中出现任何错误导致的结果,本人不负任何责任. 如果有任何翻译错误,以及意见与建议,请email本人.邮件地址:[email protected]. 转载请注

Common Lisp学习资源整理

Lisp Hackers: Interviews with 100x More Productive Programmers Posted on June 26th, 2013 Lisp Hackers: Interviews with 100x More Productive Programmers, by Vsevolod Dyomkin, is available for free in multiple formats from Leanpub. Let Over Lambda Post