练习

  (1)编写代码,定义一个基类 MyClass,其中包含虚拟方法 GetString()。这个方法应返回存储在受保护字段 myString 中的字符串,该字段可以通过只写公共属性 ContainedString 来访问。

答案:

  1. class MyClass
    {
    protected string myString;

    public string ContainedString
    {
    set
    {
    myString = value;
    }
    }

    public virtual string GetString()
    {
    return myString;
    }
    }


  (2)从类 MyClass 中派生一个类 MyDerivedClass。重写 GetString() 方法,使用该方法的基类实现代码从基类中返回一个字符串,但在返回的字符串中添加文本 “(output from derived class)”。

答案:

  1. class MyDerivedClass : MyClass
    {
    public override string GetString()
    {
    return base.GetString() + " (output from derived class)";
    }
    }


  (3)部分方法定义必须使用 void 返回类型。说明其原因。

答案:  如果方法具有返回类型,就可以将其用作表达式的一部分:

  1. x = Manipulate(y, z);


  如果没有给部分方法提供实现代码,编译器就会在使用该部分方法的所有地方删除该方法。在上面的代码中,这会使x的结果变得模糊,因为Manipulate()方法没有替代方法。如果没有这个方法,可能只需忽略整行代码,但编译器无法确定我们是否的确希望忽略它。  没有返回类型的方法不能作为表达式的一部分来调用,所以编译器可以安全地删除对部分方法调用的所有引用。  同样,也禁止使用out参数,因为在方法调用之前,用作out参数的变量必须是未定义的,而应在方法调用之后定义。而应在方法调用之后定义。删除方法定义会违反这个规则。

  (4)编写一个类 MyCopyableClass,该类可以使用方法 GetCopy() 返回它本身的一个副本。这个方法应使用派生于 System.Object 的 MemberwiseClone() 方法。给该类添加一个简单的属性,并且编写客户代码,客户代码使用该类检查任务是否成功执行。

答案:

  1. class MyCopyableClass
    {
    protected int myInt;

    public int ContainedInt
    {
    get
    {
    return myInt;
    }
    set
    {
    myInt = value;
    }
    }
    public MyCopyableClass GetCopy()
    {
    return (MyCopyableClass)MemberwiseClone();
    }
    }


  客户端代码:

  1. class Program
    {
    static void Main(string[] args)
    {
    MyCopyableClass obj1 = new MyCopyableClass();
    obj1.ContainInt = 5;
    MyCopyableClass obj2 = obj1.GetCopy();
    obj1.ContainedInt = 9;
    Console.WriteLine(obj2.ContainedInt);
    }
    }


  这些代码显示5,说明所复制对象有自己专用的myInt字段。

  (5)为 Ch10CardLib 库编写一个控制台客户程序,从洗牌后的 Deck 对象中一次取出 5 张牌。如果这 5 张牌都是相同花色,客户程序就应在屏幕上显示这 5 张牌,以及文本 "Flush!",否则在取出 50 张牌以后就输出文本 “No flush”,并退出。

答案:

  1. using System;
    using Ch10CardLib;

    namespace Exercise_Answers
    {
    class Class1
    {
    static void Main(string[] args)
    {
    while(true)
    {
    Deck playDeck = new Deck();
    playDeck.Shuffle();
    bool isFlush = false;
    int flushHandIndex = 0;
    for(int hand = 0; hand < 10; hand++)
    {
    ifFlush = true;
    Suit flushSuit = playDeck.GetCard(hand 5).suit;
    for(int card = 1; card < 5; card++)
    {
    if(playDeck.GetCard(hand
    5 + card).suit != flushSuit)
    {
    isFlush = false;
    }
    }
    if(isFlush)
    {
    flushHandIndex = hand * 5;
    break;
    }
    }
    if(isFlush)
    {
    Console.WriteLine("Flush!");
    for(int card = 0; card < 5; card++)
    {
    Console.WriteLine(playDeck.GetCard(flushHandIndex + card));
    }
    }
    else
    {
    Console.WriteLine("No flush.");
    }
    Console.ReadLine();
    }// end while
    }// end Main
    }
    }


  这些代码会循环下去,因为同花色是不常见的。可能需要按几次回车键,才能在洗好的扑克牌中找到一个同花色。为了验证一切如期执行,可以尝试将洗牌的代码行注释掉。