• 沒有找到結果。

CSharp355Spring2022 Zheng-LiangLu C#Programming

N/A
N/A
Protected

Academic year: 2022

Share "CSharp355Spring2022 Zheng-LiangLu C#Programming"

Copied!
83
0
0

加載中.... (立即查看全文)

全文

(1)

C# Programming

Zheng-Liang Lu

Department of Computer Science & Information Engineering National Taiwan University

CSharp 355 Spring 2022

(2)

1 class Lecture6

2 {

3

4 "Object−Oriented Programming (OOP)"

5 6 }

7

8 // Keywords:

9 class, new, private, public, get, set, value, const, readonly,

10 this, static, null, object, virtual, override, as, is, abstract,

11 sealed, interface, delegate, struct, enum, protected, internal,

12 namespace, using

Zheng-Liang Lu C# Programming 193

(3)

“Object-oriented programming is an exceptionally bad idea which could only have originated in California.”

– Edsger Dijkstra (1930-2002)

“Objects are abstractions of processing. Threads are ab- stractions of schedule.”

– James O. Coplien

(4)

Object & Class

• An object is an entity to maintain its own states in fields1 and provide accessorymethods (or actions) on fields.

• To create objects of this type, we define a new classas follows:

Designate a name with the first letter capitalized;

Declare data and function members in the class body.

• Note that a class is one way to create reference types.2

• In this sense,defining a new class is to define a new type!

You are building a new world!

1It is also called attributes, properties, and whatsoever.

2For example, we will visit more reference types, likeinterfaceanddelegate.

Zheng-Liang Lu C# Programming 195

(5)

Example: Points

• For any 2D point, the class could look like the code snippet below:

1 class Point

2 {

3 // Data members.

4 public double x, y;

5 }

• Then we manipulate two points in another class, shown in the next page.

(6)

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 Point p1 = new Point();

6 p1.x = 10;

7 p1.y = 20;

8

9 Point p2 = new Point();

10 p2.x = 30;

11 p2.y = 40;

12

13 Console.WriteLine("p1 = ({0, 2}, {1, 2})", p1.x, p1.y);

14 Console.WriteLine("p2 = ({0, 2}, {1, 2})", p2.x, p2.y);

15 }

16 }

• Could you sketch the memory allocation when the program reaches Line 13?

• What if we remove publicin Line 3?

• Note that these two fields are private without stated explicitly.

Zheng-Liang Lu C# Programming 197

(7)

Encapsulation

• Each member has an access level3, say public andprivate:

public: accessible by any class.

private: accessible only within its own class.

• In OOP practice, the internals like data members should be isolatedfrom the outside world.

• We then expose the publicmethods which perform actions on these fields if necessary.

• In newer C#, we declare propertieswhich look like fields but with get or set added.

(8)

Example: Point (Encapsulated)

1 class Point

2 {

3 // Data members: private fields

4 private double x , y ;

5

6 // Data members: properties

7 public double X

8 {

9 get { return x ; }

10 set { x = value; }

11 }

12

13 public double Y

14 {

15 get { return y ; }

16 set { y = value; }

17 }

18 }

1 class Point {

2

3 // Automatic properties

4 public double X { get; set; }

5 public double Y { get; set; }

6 7 }

• You cannot read (write) the value without the property accessorget (set).

Zheng-Liang Lu C# Programming 199

(9)

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 Point p1 = new Point();

6 p1.X = 10;

7 p1.Y = 20;

8

9 ...

10 }

11 }

• Although properties are accessed in the same way as fields, they differ in that properties give youcomplete control over getting and setting its values.

• You may take a look at the init-only setter init.4

(10)

Constructors

• To create an object of the type, its constructor is invoked by thenew operator.

• You can define constructors with parameters if necessary.

For example, initializing x and y of some Point object.

• Note that a constructor has its name identical to the class name and has noreturn type. (Why?)

• If there is no explicit constructor, C# assumes a default constructorfor you.

• Adding any explicit constructor disables it but you can recover it by youself.

Zheng-Liang Lu C# Programming 201

(11)

Parameterized Constructors: Example

1 class Point

2 {

3 ...

4 public Point()

5 {

6 // Do something in common.

7 }

8

9 // Parameterized constructor

10 public Point(double x, double y)

11 {

12 X = x; // Equivalent to x = x.

13 Y = y; // Equivalent to y = y.

14 }

15 ...

16 }

(12)

Object Elimination: Garbage Collection

6

• The garbage collector (GC) serves as the automatic memory manager for the CLR.

• It reclaims the memory space occupied by the objects which are no longer being used (referenced) by the application.

• The further detail about the GC and memory management can be found in the official document.5

5SeeFundamentals of Garbage Collection.

6Seehttps://docs.microsoft.com/en-us/dotnet/api/system.gc.

Zheng-Liang Lu C# Programming 203

(13)

Design Tool: Unified Modeling Language (UML)

8

• We could conduct one object-oriented analysis and designby using UML which specifies, visualizes, constructs, and documents the artifacts of software systems and business modeling.7

7You could try some UML softwares, sayStarUML.

(14)

Photo credit: screenshot fromhttp://staruml.io/.

Zheng-Liang Lu C# Programming 205

(15)

Example: Class Diagram

• Try to implement this class according to the diagram.

(16)

1 class Point

2 {

3 public double X { get; set; }

4 public double Y { get; set; }

5

6 public Point() { }

7 public Point(double x, double y) { X = x; Y = y; }

8

9 public double GetDistanceFrom(Point that)

10 {

11 return Math.Sqrt(Math.Pow(this.X − that.X, 2)

12 + Math.Pow(this.Y − that.Y, 2));

13 }

14 }

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 // Ignore the code snippet shown before.

6 Console.WriteLine("Distance = {0}", p1.GetDistanceFrom(p2));

7 }

8 }

Zheng-Liang Lu C# Programming 207

(17)

Has-A Relationship

• Associationis a weak relationship where all objects have their own lifetime and there is no ownership.

For example, teacher ↔ student; doctor ↔ patient.

• Aggregationemphasizes that A uses B and B could exist independently from A.

For example, knight ↔ sword; company ↔ employee.

• Composition stands for the case that A owns B and B has no meaning or purpose in the system without A.

For example, house ↔ room.

(18)

Example: (Straight) Line

• +2: one Line object uses two Point objects.

• What kind of has-a relationships the class Line use?

Zheng-Liang Lu C# Programming 209

(19)

1 class Line

2 {

3 public Point Head { get; set; }

4 public Point Tail { get; set; }

5

6 public Line(Point head, Point tail)

7 {

8 Head = head; Tail = tail;

9 }

10

11 public double GetLength()

12 {

13 return Head.GetDistanceFrom(Tail); // Do not repeat youself.

14 }

15 }

• The single responsibility principle9 states that every type should be responsible for only one thing.

High cohesion, low coupling.

The Hollywood principle: don’t call us, we’ll call you.

(20)

Exercise: Circles

1 class Circle

2 {

3 public Point Center { get; set; }

4 public double Radius { get; set; }

5

6 public Circle(Point c, double r) { Center = c; Radius = r; }

7 public double GetArea() { return Radius * Radius * Math.PI; }

8

9 public boolean IsOverlapped(Circle that)

10 {

11 return this.Radius + that.Radius>

12 this.Center.GetDistanceFrom(that.Center);

13 }

14 }

• Usethis to specify which X and Y are referred.

Zheng-Liang Lu C# Programming 211

(21)

Exercise: Triangle

1 class Triangle

2 {

3 public Point[] Nodes { get; }

4 private double perimeter = 0; // Cache the result to save time.

5

6 public Triangle(Point p1, Point p2, Point p3)

7 {

8 Nodes = new Point[] { p1, p2, p3 };

9 for (int i = 0; i < Nodes.Length; i++)

10 perimeter += Nodes[i].GetDistanceFrom(Nodes[(i + 1) % 3]);

11 }

12 public Triangle(params Point[] points) { Nodes = points; }

13

14 public double Perimeter() { return perimeter; }

15 }

• This makes Triangleimmutable, meaning that the Triangle object cannot change its nodes once it is created.

(22)

To Be static or Not?

11

• You must notice that both data and function members are declared w/ostatic in this chapter.

• These members are called instance memberswhich are available only after one object is created.

• Those static members (variables and methods) are not part of objects but belong to its class.

For example, Math.PI isstaticandconstant.10

• In particular, staticmethods perform algorithms.

For example, Math.Sqrt() and Array.Sort().

10Theconstantvariables cannot change their value and should be initialized in the declaration. Addingstaticandconstantto a variable makes it a global constant, like the π value. Seeconst (C# reference).

11Seestatic (C# reference).

Zheng-Liang Lu C# Programming 213

(23)

Example: Point (Revisited)

1 class Point

2 {

3 /* Ignore the previous part. */

4 public static double Measure(Point first, Point second)

5 {

6 // You cannot use this in static context.

7 return Math.Sqrt(Math.Pow(first.X − second.X, 2)

8 + Math.Pow(first.Y − second.Y, 2));

9 }

10 }

1 class Porgram

2 {

3 static void Main(string[] args)

4 {

5 /* Ignore the previous part. */

6 Console.WriteLine(Point.Measure(p1, p2));

7 }

8 }

(24)

Digression: Design Patterns

• Design patterns are a collection of general reusable solutions to a commonly occurring problem in software design.12

• These patterns fulfill experience reuseinstead of coded reuse.

• To my personal experience,OOP syntaxes is the structural skeleton; design patterns are the flesh and blood.

• If you wonder why we need OOP and how to exploit it, I suggest that you could follow any textbook13 or studying materials for design patterns.

12Gamma et al. (1994): Design Patterns: Elements of Reusable Object-Oriented Software.

13For example, Freeman and Robson (2020): Head First Design Patterns.

Zheng-Liang Lu C# Programming 215

(25)

Example: Singleton Pattern

• For some situations, you need only one object of this type in the system.

1 class Singleton

2 {

3 // Do now allow to invoke the constructor by others.

4 Singleton() { }

5

6 // Create by itselt and cache it by one static variable.

7 public static Singleton Instance { get; } = new Singleton();

8 9 }

(26)

First Is-A Relationship: Class Inheritance

• We can define new classes by inheritingthose members commonly used in predefined classes like prototypes.

• A derivedclass inherits from itsbaseclass by using the colon operator (:), for example,

1 // Base class.

2 class A

3 {

4 public void DoAction() { } // A can run DoAction().

5 }

6 // Derived class.

7 class B : A { } // B can also run DoAction().

• Note that C# supports onlysingle inheritance.

Zheng-Liang Lu C# Programming 217

(27)

Example: Human & Dog

Photo credit:https://www.sunnyskyz.com/uploads/2016/12/nlf37-dog.jpg

(28)

Before Using Inheritance

1 class Human

2 {

3 public void Eat() { }

4 public void Exercise() { }

5 public void WriteCode() { }

6 }

1 class Dog

2 {

3 public void Eat() { }

4 public void Exercise() { }

5 public void WagTail() { }

6 }

Zheng-Liang Lu C# Programming 219

(29)

After Using Inheritance

Animal

Human Dog

• Extract the common part between Human and Dog to another class, say Animal, as their base class.

• Then Human and Dog both inherit the Eat and Exercise methods from Animal.

(30)

1 class Animal

2 {

3 public void Eat() { }

4 public void Exercise() { }

5 }

1 class Human : Animal

2 {

3 public void WriteCode() { }

4 }

1 class Dog : Animal

2 {

3 public void WagTail() { }

4 }

Zheng-Liang Lu C# Programming 221

(31)

Exercise: Add Cat to Animal Hierarchy

Photo credit:https://cdn2.ettoday.net/images/2590/2590715.jpg

(32)

Animal

Human Dog

Cat

1 class Cat : Animal

2 {

3 public void Stepping() { }

4 }

• You can add more animals by simply extending Animal!

• It is, again, code reuse.

Zheng-Liang Lu C# Programming 223

(33)

Constructor Chaining

• When one constructor of the derived class is invoked, the constructor of its base class will also be invoked.

• So there is a chain of constructor invocations, all the way back to the constructor of the topmost class in C#, called Object.

Theobjectkeyword is the alias of Object.

• In this sense, we can say that every class is an immediate or a distant derived class of Object.

(34)

Illustration for Class Hierarchy

Zheng-Liang Lu C# Programming 225

(35)

Self References: this & base

• You can usethisto select any instance member of the current object in its methods and constructors.

• It is similar to usebase for any instance member of its base class.

• Note that any invocation likethis() andbase() is to invoke its constructor.

(36)

Method Overriding

14

• A derived class is supposed to implementthevirtual methods inherited from its base class.

• Note that you cannot override a non-virtual or staticmethod.

1 class A

2 {

3 public virtual void DoAction() { /* Impl. */ }

4 }

5

6 class B: A

7 {

8 public override void DoAction()

9 {

10 /* New impl. w/o changing API. */

11 }

12 }

14Seevirtual (C# reference)andoverride (C# reference).

Zheng-Liang Lu C# Programming 227

(37)

Conceptual Example

(38)

Example

1 class Animal

2 {

3 /* Ignore the previous part. */

4 public virtual void Eat() { }

5 }

6

7 class Human

8 {

9 /* Ignore the previous part. */

10 public override void Eat()

11 {

12 Console.WriteLine("Eating with chopsticks...");

13 }

14 }

15

16 class Dog

17 {

18 /* Ignore the previous part. */

19 public override void Eat()

20 {

21 Console.WriteLine("Eating on the ground...");

22 }

23 } Zheng-Liang Lu C# Programming 229

(39)

Another Example: ToString()

• The ToString method defined in Object is deliberately designed to be invoked by Console.WriteLine()!

• By default, it returns the type name, but not informative.

• It may return any string in need by overriding the ToString method.

• We will revisit this example later.

(40)

1 class Point

2 {

3 /* Ignore the previous part. */

4 public override string ToString()

5 {

6 return String.Format("({0}, {1})", x, y);

7 }

8 }

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 /* Ignore the previous part. */

6 // Console.WriteLine("p1 = ({0, 2}, {1, 2})", p1.x, p1.y);

7 // Console.WriteLine("p2 = ({0, 2}, {1, 2})", p2.x, p2.y);

8

9 Console.WriteLine("p1 = {0}", p1); // Short and sweet?

10 Console.WriteLine("p2 = {0}", p2);

11 }

12 }

Zheng-Liang Lu C# Programming 231

(41)

Subtype Polymorphism

16

• The word polymorphismliterally means “many forms.”

• One of OOP design rules is toseparate the interface from implementationsand program to abstraction, not to implementation.15

• Subtype polymorphism fulfills this rule.

• How to make a “single” interface for different implementations?

Use thebase classof those types as theplaceholder.

15Gamma et al. (1994). The original sentence is “program to interface, not to implementation.”

(42)

Example: Animal (Revisited)

1 class Program // before decoupling

2 {

3 static void GoDinner(Human someone) { someone.Eat(); }

4 static void Main(string[] args)

5 {

6 Human arthur = new Human();

7 GoDinner(arthur);

8 Dog lucky = new Dog();

9 GoDinner(lucky); // Oops!

10 }

11 }

• You cannot pass a dog to the GoDinner method. (Why?)

• How to decouple this dependency?

Zheng-Liang Lu C# Programming 233

(43)

1 class Program // after decoupling

2 {

3 static void GoDinner(Animal someone)

4 {

5 someone.Eat();

6 }

7

8 static void Main(string[] args)

9 {

10 Animal arthur = new Human();

11 GoDinner(arthur);

12 Animal lucky = new Dog();

13 GoDinner(lucky); // It works!

14 }

15 }

• A variable of the basetype can manipulate the object of its type or derived types.

• Thus the basetype works as a client interface, separating what to use and how to use.

• This example illustrates the protocal between ToString and

(44)

Dynamic Binding

• When calling an overriden method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method.

• It is also called late binding, in comparison to early (static) binding.

Zheng-Liang Lu C# Programming 235

(45)

Digression: Why We Need OOP?

17

• OOP is the solid foundation of modern (large-scale) software design.

• In particular, great reusemechanism andabstraction are realized by these three concepts:

encapsulationisolates the internals (private members) from the externals, fulfilling the abstraction and providing the sufficient accessibility (public methods);

inheritanceprovides method overriding w/o changing the method signature;

polymorphismexploits the base class as a placeholder to manipulate the implementations (subtype objects).

• We usePIE as the shorthand for these three concepts.

(46)

Zheng-Liang Lu C# Programming 237

(47)

• This leads to the production offrameworks18, which actually do most of the job, leaving the (application) programmer only with the job of customizing withbusiness logic rules and providing hooks into it.

• This greatly reduces programming time and makes feasible the creation of larger and larger systems.

• In analog, we often manipulate objects in an abstract level; we don’t need to know the details when we use them.

For example, using computers and cellphones, driving a car, and so on.

18Seehttps://docs.microsoft.com/en-us/dotnet/core/and

(48)

Another Example

1 class Animal

2 {

3 public virtual void Speak() {}

4 }

5

6 class Dog : Animal

7 {

8 public override void Speak() { Console.WriteLine("Woof! Woof!"); }

9 }

10

11 class Cat : Animal

12 {

13 public override void Speak() { Console.WriteLine("Meow˜"); }

14 }

15

16 class Bird : Animal

17 {

18 public override void Speak() { Console.WriteLine("Tweet!"); }

19 }

Zheng-Liang Lu C# Programming 239

(49)

1 class PolymorphismDemo2

2 {

3 static void Main(string[] args)

4 {

5 Animal[] animals = { new Dog(), new Cat(), new Bird() };

6

7 foreach (Animal animal in animals) {

8 animal.Speak();

9 }

10 }

11 }

• Again, Animal is a placeholder for the three derived types.

(50)

Liskov Substitution Principle

19

• For convenience, let U be a subtype of T.

• We manipulate objects (right-hand side) via references (left-hand side)!

• Liskov states that T-type objects may be replaced with U-type objects without altering any of the desirable properties of T (correctness, task performed, etc.).

19Seehttps://en.wikipedia.org/wiki/Liskov substitution principle.

Zheng-Liang Lu C# Programming 241

(51)

Casting

• Upcasting20 is to cast the U object/variable to the T variable.

1 U u1 = new U(); // Trivial.

2 T t1 = u1; // OK.

3 T t2 = new U(); // OK.

• Downcasting21 is to cast the T variable to a U variable.

1 U u2 = t2 as T; // OK, but dangerous. Why?

2 U u3 = new T(); // Error! Why?

• Note that theas operator explicitly converts the result of an expression to a given reference or nullable value type.

20A widening conversion; back compatibility.

(52)

Solution: is

• Upcasting is wanted and always allowed. (Why?)

• However, downcasting is not always true even when you use cast operators.

In fact, type checking at compile time becomes unsound if any cast operator is used. (Why?)

• Even worse, a T-type variable can point to all siblings of U-type.

Recall that a T-type variable works as a placeholder.

• Run-time type information (RTTI) is needed to resolve the error: InvalidCastException.

• We can useis to check if the referenced object is of the target type at runtime.

Zheng-Liang Lu C# Programming 243

(53)

Example

A

B C

D E

F

• The class inheritance can be represented by adigraph (directed graph).

• For example, D is a subtype of A and B, which are both reachable from D on the digraph.

(54)

1 class A {}

2 class B : A {}

3 class C : A {}

4 class D : B {}

5 class E : B {}

6 class F : D {}

7

8 class RTTI Demo

9 {

10 public static void Main(string[] args)

11 {

12 Object o = new D();

13

14 Console.WriteLine(o is A); // Output true.

15 Console.WriteLine(o is B); // Output true.

16 Console.WriteLine(o is C); // Output false.

17 Console.WriteLine(o is D); // Output true.

18 Console.WriteLine(o is E); // Output false.

19 Console.WriteLine(o is F); // Output false.

20 }

21 }

Zheng-Liang Lu C# Programming 245

(55)

Abstract Methods/Classes

• A method without implementation can be declared abstract.

The method has no brace butends by a semicolon.

• If a class has one or more abstractmethods, then the class itself must be declared abstract.

• Typically, oneabstract class sits at the top of one class hierarchy, acting as an placeholder.

• Noabstract class cannot be instantiated directly.

• When inheriting an abstractclass, the editor could help you recall every abstract methods.

(56)

Example

• In UML, abstract methods and classes are presented in italic.

• The method Draw () and Resize() can be implemented when the specific shape is known.

Zheng-Liang Lu C# Programming 247

(57)

The sealed Keyword

22

• When applied to a class, the sealed modifier prevents other classes from inheriting from it.

1 class A {}

2 sealed class B : A {}

3 class C : B {} // You cannot extend C by inheriting from B.

22See

(58)

Misc: constant & readonly

23

• You use theconstant keyword to declare a constant field or a constant local, which is called immutable.

• This means that its value cannot be changed over time.

• Similarly, readonly indicates that assignment to the field can only occur as part of the field declaration or in a constructor.

• The main difference between constandreadonly is that a const field is a compile-timeconstant, thereadonly field can be used for run-timeconstants.

• Thereadonly fields can have different values depending on the constructor used.

23Seeconst (C# reference)andreadonly (C# reference).

Zheng-Liang Lu C# Programming 249

(59)

Another IS-A Relationship: Interface Inheritance

• Objects of different types are supposed to work together without a proper vertical relationship.

• For example, consider Bird inherited from Animal and Airplane inherited from Transportation.

• Both Bird and Airplane are able to fly in the sky, say by calling the method Fly().

• In semantics, the method Fly() could not be defined in their base classes. (Why?)

(60)

• We wish those flyable objects go flying by calling one API, just like the way of Student.

• Recall that Object is the base class of everything.

• So, how about using Object as the placeholder?

Not really. (Why?)

• Clearly, we need a horizontalrelationship: interface.

1 interface IFlyable

2 {

3 void Fly(); // Implicitly public and abstract.

4 }

Zheng-Liang Lu C# Programming 251

(61)

Object

Animal

... Bird

Transportation

Airplane ...

IFlyable

(62)

1 class Animal { }

2 class Bird : Animal, IFlyable

3 {

4 void FlyByFlappingWings()

5 {

6 Console.WriteLine("Flapping wings!");

7 }

8

9 public void Fly() { FlyByFlappingWings(); }

10 }

11

12 class Transportation { }

13 class Airplane : Transportation, IFlyable

14 {

15 void FlyByCastingMagic()

16 {

17 Console.WriteLine("#$%@$ˆ@!#$!");

18 }

19

20 public void Fly() { FlyByCastingMagic(); }

21 }

Zheng-Liang Lu C# Programming 253

(63)

https://i.imgur.com/y2bmNpz.jpg

(64)

1 class InterfaceDemo

2 {

3 static void Main(string[] args)

4 {

5 Bird owl = new Bird();

6 GoFly(owl);

7

8 Airplane a380 = new Airplane();

9 GoFly(a380);

10 }

11

12 public static void GoFly(IFlyable flyer)

13 {

14 flyer.Fly();

15 }

16 }

Zheng-Liang Lu C# Programming 255

(65)

A Deep Dive into Interfaces

• An interface is a contract between the object and the client.

• As shown, an interface is a reference type, just like classes.

• Unlike classes, interfaces are used to define methods without implementation so that theycannot be instantiated (directly).

• Also, interfaces are stateless.

• A class could implement one or multipleinterfaces!

(66)

• Note thatan interface can extend another interfaces!

Like a collection of contracts, in some sense.

• For example, IRunnable, IList, and IComparable24.

• Beginning with C# 8.0, we have new features as follows:

may define a default implementation for members;

may also definestaticmembers in order to provide a single implementation for common functionality.

24See

https://docs.microsoft.com/zh-tw/dotnet/api/system.icomparable?view=netcore-3.1.

Zheng-Liang Lu C# Programming 257

(67)

Timing for Interfaces & Abstract Classes

• Consider using abstract classes if you want to:

share code among several closely related classes, and

declare non-constantor non-staticfields.

• Consider using interfaces for any of situations as follows:

unrelated classes would implement your interface;

specify the behavior of a particular data type, but not concerned about who implements its behavior;

take advantage of multiple inheritance.

(68)

Exercise: RPG

Zheng-Liang Lu C# Programming 259

(69)

• First, Wizard, SeaDragon, and Merchant are three of Characters.

• In particular, Wizard fights with SeaDragon by invoking Attack().

• Wizard buys and sells stuffs with Merchant by invoking BuyAndSell().

• However, SeaDragon cannot buy and sell stuffs; Merchant cannot attack others.

(70)

Character

Wizard Seadragon

Merchant

ICombat ITrade

Zheng-Liang Lu C# Programming 261

(71)

1 abstract class Character {}

2

3 interface ICombat

4 {

5 void Attack(ICombat enemy);

6 }

7

8 interface ITrade

9 {

10 void BuyAndSell(ITrade counterpart);

11 }

(72)

1 class Wizard : Character, ICombat, ITrade

2 {

3 public void Attack(ICombat enemy) {}

4 public void BuyAndSell(ITrade counterpart) {}

5 }

1 class SeaDragon : Character, ICombat

2 {

3 public void Attack(ICombat enemy) {}

4 }

1 class Merchant : Character, ITrade

2 {

3 public void BuyAndSell(ITrade counterpart) {}

4 }

Zheng-Liang Lu C# Programming 263

(73)

Delegation

26

• A delegate is a type that safely encapsulates a method, similar to a function pointer in C and C++.

• The type of a delegate is defined by the name of the delegate.

• A delegate object is normally constructed by providing the name of the method the delegate will wrap, or with an anonymous function.25

• Once a delegate is instantiated, a method call made to the delegate will be passed by the delegate to that method.

25See

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions.

26See

(74)

Example

1 class Program

2 {

3 delegate double Calculator(double x, double y);

4

5 static double Add(double x, double y) { return x + y; }

6 static double Mul(double x, double y) => x * y;

7 // The above statement is presented in lambda expressions!

8

9 static void Main(string[] args)

10 {

11 Calculator calculator;

12

13 calculator = Add;

14 Console.WriteLine(calculator(10, 20)); // Output 30.

15 calculator = Mul;

16 Console.WriteLine(calculator(10, 20)); // Output 200.

17 }

18 }

Zheng-Liang Lu C# Programming 265

(75)

Another Example: Callback

1 class Program

2 {

3 delegate void Del(string message);

4

5 static void MethodWithCallback(int param1,

6 int param2,

7 Del callback)

8 {

9 callback(String.Format("Sum = {0}", param1 + param2));

10 }

11

12 static void Main(string[] args)

13 {

14 MethodWithCallback(1, 2, x => Console.WriteLine(x));

15 }

16 }

(76)

Delegation vs. Inheritance

• Class inheritance is a powerful way to achieve code reuse.

• However, class inheritance violates encapsulation!

• This is because a derived class depends on the implementation details of its base class for its proper function.

• To solve this issue, we favor delegation over inheritance.27

27GoF (1995); Also see Item 18 in Bloch (2018).

Zheng-Liang Lu C# Programming 267

(77)

Enumeration Types

28

• An enum type is a distinct value type that declares a set of named constants.

• Each enum type has a corresponding integral type called the underlying type of the enum type, say int, without explicitly declaration.

• This mechanism enhances type safety and makes the source code more readable!

• For example,

1 enum Season

2 {

3 Spring, Summer, Autumn, Winter

4 }

28See

(78)

Structure Types

29

• A structure type (or structtype) is avalue type that can encapsulate data and related functionality.

• Typically, you use structure types to design small data-centric types that provide little or no behavior.

• Because structure types have value semantics, we recommend you to define immutable structure types.

29See

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct.

Zheng-Liang Lu C# Programming 269

(79)

Example

1 public readonly struct Coords

2 {

3 public Coords(double x, double y)

4 {

5 X = x;

6 Y = y;

7 }

8

9 public double X { get; }

10 public double Y { get; }

11

12 public override string ToString() => $"({X}, {Y})";

13 }

(80)

Tuple Types

30

• Available in C# 7.0 and later, the tuples feature provides concise syntax to groupmultiple data elements.

1 ...

2 (double, int) t1 = (4.5, 3);

3 Console.WriteLine("Tuple with elements {0} and {1}.",

4 t1.Item1, t1.Item2);

5

6 (double Sum, int Count) t2 = (4.5, 3);

7 Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");

8 ...

• You may add the dollar sign ($) before the string to indicate the members in the tuple.

30See

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples.

Zheng-Liang Lu C# Programming 271

(81)

Nested Types

31

• A type defined within a class,struct, or interfaceis called a nested type.

1 class Program

2 {

3 public static Main(string[] args)

4 {

5 House home = new House();

6 // Room bedreoom = new Room(); // You cannot do this.

7 }

8 }

9

10 class House

11 {

12 class Room { } // Another HAS−A relationship: composition.

13 }

31See

(82)

Special Issue: Using Namespaces

33

• Namespaces are heavily used within C# programs in two ways.

• Firstly, the .NET classes use namespaces to organize its many classes.32

• Secondly, declaring your own namespaces can help control the scope of class and method names in larger programming projects.

• The usingdirectives facilitate the use of namespaces and types defined in other namespaces.

32The counterpart of Java is the “package.”

33See

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/namespaces.

Zheng-Liang Lu C# Programming 273

(83)

Example

1 using Toolbox;

2

3 namespace NamespaceDemo

4 {

5 using B = NestedNamespace.A;

6

7 class Program

8 {

9 static void Main(string[] args)

10 {

11 B b = new B();

12 C c = new C();

13 }

14 }

15

16 namespace NestedNamespace

17 {

18 class A {}

19 }

20 }

1 namespace Toolbox

2 {

3 public class C { }

4 }

參考文獻

相關文件

Now given the volume fraction for the interface cell C i , we seek a reconstruction that mimics the sub-grid structure of the jump between 0 and 1 in the volume fraction

In this paper, we extended the entropy-like proximal algo- rithm proposed by Eggermont [12] for convex programming subject to nonnegative constraints and proposed a class of

[r]

[r]

[r]

[r]

õT¤_ .â·&lt;íËju, Data Access Component Module 2FíŠ?. âÀÓ“, ©ø_ method úk’eé query v,

依賴背包問題 and