none
《C#入门经典》第十一章扑克牌的程序,遇到一些不知道怎么问的问题。。。问题在注释里 RRS feed

  • 问题

  • public class Card (这是Card类中相关的部分)   (或者看http://social.msdn.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/5dff31d8-1411-4bf8-a0b4-a5ef3bf4489c)

    {

    public static bool useTrumps = false;     

             public static Suit trump = Suit.Club;           

             public static bool isAceHigh = true;

    ...............................

    }

    public Deck(bool isAceHigh)
           : this()
         {
           Card.isAceHigh = isAceHigh;//isAceHigh不是bool类型的么?怎么= Card.isAceHigh 了?
                       //为什么不直接Card.isAceHigh==true好了? 
           //isAceHigh应该是一个静态字段吧?如果是静态字段的话isAceHigh不是已经赋值true了么?
           //这里又Card.isAceHigh = isAceHigh;是做什么?
         }
    
          //Nondefault constructor. Allows a trump suit to be used.
         public Deck(bool useTrumps, Suit trump)
           : this()
         {
           Card.useTrumps = useTrumps;//问题同上一个
           Card.trump = trump;//在Card类中有public static Suit trump = Suit.Club;这样一段话,
         } //不明白(public static Suit trump = Suit.Club;)和(Card.trump = trump;)是要表达什么,
          //总觉得等式左右表达的不是同一个东西。。。不知道你明白我的感觉没有。。。
    
          //Nondefault constructor. Allows aces to be set high and a trump suit
          //to be used.
         public Deck(bool isAceHigh, bool useTrumps, Suit trump)
           : this()
         {
           Card.isAceHigh = isAceHigh;
           Card.useTrumps = useTrumps;
           Card.trump = trump;
         }
    
    2010年12月9日 16:11

答案

  • dear
    看了你那麽多的问题,我知道你很认真在学习,这些范例不需要每一行都看过,你应该了解程式功能,毕竟要达到相同的功能有很多种写法,然后再用自己的想法写出来,了解类别封装、继承、多型,书上的范例你自然知道怎麽用。

    1.你的问题有列举enum,所以你该把它的用法记下来

    [[入門][Enum] Enum 詳論]
    http://www.dotblogs.com.tw/johnny/archive/2010/01/25/13300.aspx

    [[C#]將string轉為enum Convert String To Enum]
    http://www.dotblogs.com.tw/dotjum/archive/2008/02/10/1055.aspx

    [C# - ENUM (列舉) 的實作心得]
    http://www.dotblogs.com.tw/dc690216/archive/2009/09/16/10666.aspx

    [Enum的轉換,用Enum.Parse()]
    http://www.dotblogs.com.tw/wei314/archive/2009/12/30/12739.aspx

    书上的范例都是用OOP(封装、继承、多型)写的,全面了解他门的用法你自然就看的懂

    2.这范例的很不严谨,这应该要用属性写比较好
    public static bool isAceHigh = true;

    改成属性写法
    public bool isAceHigh {get;set;}

    这表示Card.isAceHigh可以透过Deck方法变更状态,当然你也可以直接拿Card.isAceHigh来改变
    public Deck(bool isAceHigh)
    {
      Card.isAceHigh = isAceHigh
    }

    但如果是我,我不会允许别人随便变数的话,我会这样用
    public bool isAceHigh {get;private set;}

    3.这也是利用方法来更改变数的值而已
    public Deck(bool useTrumps, Suit trump)
    {
       Card.useTrumps = useTrumps;
       Card.trump = trump;
    }
    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2010年12月10日 1:41
  • 这两个问题都是有关变量作用域的问题。比如:

    public class A {
        public string a;

        public void B(string a) {
            a = a;
        }
    }

    类似这种问题。也就是,a = a 到底是在干什么。

    注意,这里,左边的 a 是该实例的属性,也就是 this.a,上面那句话也可以写成 this.a = a,并且应该写成这样,这是一种编码规范,以便避免含糊不清的作用域问题。

    右边的 a 指的是作为方法参数传递进来的实际参数 a,也就是 B 声明的 string a 参数。所以,a = a 的意思就是把从方法 B 中传递过来的 a 参数的实际值,赋值给本实例 this 的一个叫 a 的属性。上面的语句等于:

    this.set_a(a);

    注意,这本书上的编码规范比较混乱,给您造成了理解上的误导。本来,属性、方法的名称按照命名约定是应该首字母大写的 (Pascal 规范),也就是,应该是 this.A = a,这样您就不会有这个问题产生了。您的代码中 card.isAceHigh = isAceHigh 就是这个问题,应该是 card.IsAceHigh = isAceHigh。

    注意,在选择一种启蒙书籍时,一定要谨慎,特别是技术类的书,一定要找一本口碑好,影响力大的翻译版的外国书籍,千万不要看国人写的。。。有些东西他们自己都没搞清楚,甚至都不是搞 C# 的人都出来写书赚钱的。


    Mark Zhou
    2010年12月10日 6:43
  • 您好,

    问:(1)Card.IsAceHigh = isAceHigh; 是把传进来的bool参数赋值给Card类中的静态bool类型的IsAceHigh字段(这里我觉得称之为字段比称之为属性更准确),这样做是为什么?

    答:这段代码写在Deck的构造函数里就是为了给客户代码在实例化Deck时可以初始化Card..IsAceHigh的值。

    问:(2)我对静态字段的理解是:基本就是常量,或者说是全局变量。但是这里                 Card.IsAceHigh = isAceHigh; 就是要给静态字段赋值!静态字段能赋值么?能这样赋值么???

    答:静态只是说,不用实例化就能访问,而不是说静态的就是常量就是不可修改的。只有被声明为const或readonly了才不能修改。

    推荐的书:Head First C#(中文版)。Head First系列都是风趣的,学起来会很轻松愉快。

    2010年12月12日 13:46
    版主
  • 第一个问题:是的,这里是把 isAceHigh 实际参数赋值给静态的 IsAceHigh 域。这样做一点好处都没有。这个设计完全是有问题的。比如,创建两次对 Card 的实例,然后传递不同的形式参数给其构造函数,这样,其静态域的值就被更改了:

    Deck c1 = new Deck(true);
    Deck c2 = new Deck(false);
    Console.WriteLine(Card.IsAceHigh) // 这里会显示 false

    假设在多线程环境中,有另外的线程同时也在创建 Deck 的实例,并传递了不同的 isAceHigh 值,那么,您可能期望 Card.IsAceHigh 的值在某段操作作用域内保持不变的想法就不可能实现了。

    第二个问题,同第一个问题的解答。静态域是与实例本身无关的一种特征,它在每一个实例中的表现是一致的,比如 String.Empty 静态域。它就表示一个空字符串。这个例子就像我说的一样,给您带来了不小的困扰。相反,如果找一本比较好的书,上面的例子可能就非常的容易理解,而不是像这本书上的,我个人从您几个星期来问的问题看,大多数是书上的例子造成了混淆和疑惑。

    我强烈推荐您购买 Microsoft Press 出版的 C# 教材,至少会有一些保证。


    Mark Zhou
    2010年12月12日 13:46

全部回复

  • dear
    看了你那麽多的问题,我知道你很认真在学习,这些范例不需要每一行都看过,你应该了解程式功能,毕竟要达到相同的功能有很多种写法,然后再用自己的想法写出来,了解类别封装、继承、多型,书上的范例你自然知道怎麽用。

    1.你的问题有列举enum,所以你该把它的用法记下来

    [[入門][Enum] Enum 詳論]
    http://www.dotblogs.com.tw/johnny/archive/2010/01/25/13300.aspx

    [[C#]將string轉為enum Convert String To Enum]
    http://www.dotblogs.com.tw/dotjum/archive/2008/02/10/1055.aspx

    [C# - ENUM (列舉) 的實作心得]
    http://www.dotblogs.com.tw/dc690216/archive/2009/09/16/10666.aspx

    [Enum的轉換,用Enum.Parse()]
    http://www.dotblogs.com.tw/wei314/archive/2009/12/30/12739.aspx

    书上的范例都是用OOP(封装、继承、多型)写的,全面了解他门的用法你自然就看的懂

    2.这范例的很不严谨,这应该要用属性写比较好
    public static bool isAceHigh = true;

    改成属性写法
    public bool isAceHigh {get;set;}

    这表示Card.isAceHigh可以透过Deck方法变更状态,当然你也可以直接拿Card.isAceHigh来改变
    public Deck(bool isAceHigh)
    {
      Card.isAceHigh = isAceHigh
    }

    但如果是我,我不会允许别人随便变数的话,我会这样用
    public bool isAceHigh {get;private set;}

    3.这也是利用方法来更改变数的值而已
    public Deck(bool useTrumps, Suit trump)
    {
       Card.useTrumps = useTrumps;
       Card.trump = trump;
    }
    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2010年12月10日 1:41
  • 这两个问题都是有关变量作用域的问题。比如:

    public class A {
        public string a;

        public void B(string a) {
            a = a;
        }
    }

    类似这种问题。也就是,a = a 到底是在干什么。

    注意,这里,左边的 a 是该实例的属性,也就是 this.a,上面那句话也可以写成 this.a = a,并且应该写成这样,这是一种编码规范,以便避免含糊不清的作用域问题。

    右边的 a 指的是作为方法参数传递进来的实际参数 a,也就是 B 声明的 string a 参数。所以,a = a 的意思就是把从方法 B 中传递过来的 a 参数的实际值,赋值给本实例 this 的一个叫 a 的属性。上面的语句等于:

    this.set_a(a);

    注意,这本书上的编码规范比较混乱,给您造成了理解上的误导。本来,属性、方法的名称按照命名约定是应该首字母大写的 (Pascal 规范),也就是,应该是 this.A = a,这样您就不会有这个问题产生了。您的代码中 card.isAceHigh = isAceHigh 就是这个问题,应该是 card.IsAceHigh = isAceHigh。

    注意,在选择一种启蒙书籍时,一定要谨慎,特别是技术类的书,一定要找一本口碑好,影响力大的翻译版的外国书籍,千万不要看国人写的。。。有些东西他们自己都没搞清楚,甚至都不是搞 C# 的人都出来写书赚钱的。


    Mark Zhou
    2010年12月10日 6:43
  • 非常感谢你的回答,我的疑问解决了一半,剩下的一般是:

    前面声明过:   public static bool IsAceHigh = true;

    后面的Deck类里:

    public Deck(bool isAceHigh)
           : this()
         {
           Card.IsAceHigh = isAceHigh; 

             .......}

        我要问的问题是:(1)Card.IsAceHigh = isAceHigh; 是把传进来的bool参数赋值给Card类中的静态bool类型的IsAceHigh字段(这里我觉得称之为字段比称之为属性更准确),这样做是为什么?

    (2)我对静态字段的理解是:基本就是常量,或者说是全局变量。但是这里                 Card.IsAceHigh = isAceHigh; 就是要给静态字段赋值!静态字段能赋值么?能这样赋值么???

    另外再多说一句,我看的是《C#入门经典第四版》,还有比这更好的?!英文版的免了啊。


    C# 菜鸟中的雏鸟!提的问题也许很幼稚,但我是认真的。希望看在党国的面子上拉兄弟一把!
    2010年12月10日 16:30
  • dear
    1.静态变量可以拿来当全域变量,当然可以丢东西进去,常量的关键字是const不是static

    2.我觉得你可以往design pattern前进,推荐程杰写的"大话设计模式"
    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2010年12月10日 17:25
  • 您好,

    问:(1)Card.IsAceHigh = isAceHigh; 是把传进来的bool参数赋值给Card类中的静态bool类型的IsAceHigh字段(这里我觉得称之为字段比称之为属性更准确),这样做是为什么?

    答:这段代码写在Deck的构造函数里就是为了给客户代码在实例化Deck时可以初始化Card..IsAceHigh的值。

    问:(2)我对静态字段的理解是:基本就是常量,或者说是全局变量。但是这里                 Card.IsAceHigh = isAceHigh; 就是要给静态字段赋值!静态字段能赋值么?能这样赋值么???

    答:静态只是说,不用实例化就能访问,而不是说静态的就是常量就是不可修改的。只有被声明为const或readonly了才不能修改。

    推荐的书:Head First C#(中文版)。Head First系列都是风趣的,学起来会很轻松愉快。

    2010年12月12日 13:46
    版主
  • 第一个问题:是的,这里是把 isAceHigh 实际参数赋值给静态的 IsAceHigh 域。这样做一点好处都没有。这个设计完全是有问题的。比如,创建两次对 Card 的实例,然后传递不同的形式参数给其构造函数,这样,其静态域的值就被更改了:

    Deck c1 = new Deck(true);
    Deck c2 = new Deck(false);
    Console.WriteLine(Card.IsAceHigh) // 这里会显示 false

    假设在多线程环境中,有另外的线程同时也在创建 Deck 的实例,并传递了不同的 isAceHigh 值,那么,您可能期望 Card.IsAceHigh 的值在某段操作作用域内保持不变的想法就不可能实现了。

    第二个问题,同第一个问题的解答。静态域是与实例本身无关的一种特征,它在每一个实例中的表现是一致的,比如 String.Empty 静态域。它就表示一个空字符串。这个例子就像我说的一样,给您带来了不小的困扰。相反,如果找一本比较好的书,上面的例子可能就非常的容易理解,而不是像这本书上的,我个人从您几个星期来问的问题看,大多数是书上的例子造成了混淆和疑惑。

    我强烈推荐您购买 Microsoft Press 出版的 C# 教材,至少会有一些保证。


    Mark Zhou
    2010年12月12日 13:46
  • 你好

    一般的静态字段可以改变啊,只是静态字段属于类,而实例字段属于对象

    readonly的静态字段只可以在初始化或者构造方法里面赋值或者改变,其余地方则只能访问不能改变

    常量只能在定义时赋值 不能改变

    Card.IsAceHigh = isAceHigh就是在代码中实例化deck时给Card的静态字段初始化

    2010年12月13日 3:45