【问题标题】:Unable to instantiate class with constructor无法使用构造函数实例化类
【发布时间】:2014-05-11 00:41:14
【问题描述】:

我很确定这是重复的,但经过几个小时的搜索/尝试后,我无法找到解决此问题的方法。

我不是高级程序员,但我有相当多的 C++ 经验。我正在尝试学习 C# 并且遇到了非常基本的语法问题,尤其是对于仅访问其他类的问题。一段时间以来,我一直在寻找简单的示例,而且绝大多数情况下,我发现的所有内容似乎都使用了一个 HUGE 类,其中使用了 main 方法,因此这些示例并没有太大帮助。

我想开发一个解决方案,其中包含多个 .cs 文件(每个文件一个类)和另一个包含我将用于测试的主要方法的 .cs 文件。我的解决方案名为 DIVAT。我有一个包含以下代码的 Dealer.cs 文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DIVAT
{
    public class Dealer
    {
        public List<Tuple<int, string>> deck;

        Dealer()
        { // default constructor
            Console.Out.WriteLine("Default constructor called. (Dealer class)");

            string [] suitValue = {"c", "d", "h", "s"};

            for(int i = 2; i <= 14; i++){
                for(int j = 0; j <= 3; j++){
                    deck.Add(new Tuple<int, string>(i, suitValue[j]));
                }            
            }
        }

        ~Dealer() 
        {// destructor
            Console.Out.WriteLine("Destrcutor called. (Dealer class)");
        }

        Tuple<int, string> Dealer.getCard(int cardNum)
        {// getter
            return deck[cardNum];
        }
    }
}

现在我只是想在另一个文件 Program.cs 中对此进行测试。我遇到了 2 个错误,但不知道为什么。我在尝试初始化我的 Dealer 类时遇到了很多麻烦。另外,我只想在我的 Dealer 类中测试一个 getter 函数。

我过去常常使用更多静态和私有关键字,但在遇到错误时将其删除。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DIVAT
{
    class Program
    {
        static void Main(string[] args)
        {
            Dealer dealer = new Dealer();
            // inaccessible due to it's protection level...

            for (int i = 0; i <= 52; i++) {                
                Console.Out.WriteLine(dealer.getCard(i));
                // does not contain a definition for getCard...
            }


        }
    }
}

很抱歉这些基本问题,但我一直在互联网上搜索并尝试不同的方法来解决这个问题,但没有成功。我觉得一旦我克服了这几个错误,我应该能够相对轻松地转换我的许多其他代码。

【问题讨论】:

  • 作为旁注,您应该为deck 使用属性(例如public List&lt;Tuple&lt;int, string&gt;&gt; deck { get; private set; }。我还添加了一个访问修饰符以设置为private,因为在这种情况下,您可能不希望经销商以外的任何班级改变牌组:)
  • 扩展我关于转换 field to a property 的评论,如果您每个人都需要向事件添加代码,方法 getsset 一个值,它根本不能作为一个字段来完成。如果它是一个属性,那么您可以更改 get/set 的工作方式,而不会影响任何其他依赖于获取/设置值的代码(非破坏性更改与破坏性更改)。

标签: c# class constructor initialization


【解决方案1】:

您的构造函数是隐式私有的,并且由于您提供零个公共构造函数,因此即使类本身是公共的,它也无法实例化您的类。..

您需要指定它是公开的。

public Dealer() { }

至于你的第二个问题,你不需要告诉你的方法它们属于这个类。他们已经意识到了。像这样更改您的方法签名:

public Tuple<int, string> GetCard(int cardNum)
{
    // getter
    return deck[cardNum];
}

请注意,现在该方法是公共的,并且我们的范围是正确的。此外,请注意方法名称上的 PascalCasing。这是 C# 中方法名称的适当命名约定。

另外,另一方面,由于 C# 是一种托管语言,您可能不需要析构函数。

【讨论】:

  • 谢谢!然后我的 getCard 函数出现错误:“显式接口声明中的'经销商'不是接口”。我读到 C# 使用 .而不是 :: 来声明函数。我使用不正确吗?即使我在 getCard 函数前面使用 public 也会发生这种情况。
  • @Clark 在这种情况下,您不需要告诉您的 Dealer 类来包含 getCard 函数。仅通过存在于类中就已经正确地确定了范围。抱歉,更新第二个问题的答案很慢。请查看我最近的更新。
  • @ErikPhilips 谢谢你的链接:)。我知道它就在外面的某个地方。是的,这正是我所指的。
  • @Clark Erik 已经回答了这个问题,但我强烈建议创建另一个问题,以便他可以将他的答案移至该问题并获得功劳。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多