【问题标题】:How to implement the default constructor (using constructor chaining) that sets the Category to Miscellaneous如何实现将 Category 设置为 Miscellaneous 的默认构造函数(使用构造函数链接)
【发布时间】:2017-03-11 06:26:49
【问题描述】:

我对编程很陌生,所以我试图做一些工作,但遇到了我的问题。 这是我的代码:

//Properties
private static readonly List<string> category = new List<string> 
{ 
    "Electric", 
    "Household", 
    "Garden", 
    "Miscellaneous" 
};

类别必须是“只读”

// Constructor
public Product(List<string> category)
{
    // this.category shows error that it cannot be accessed with an instance reference; 
    // qualify it with a type name instead
    this.category = category;
}

在默认构造函数中我也不能通过它

// Default Constructor
public Product() : this("Miscellaneous")
{
}

那么,如何在列表中传递 1 个字符串?或者我应该为此使用数组吗?以后如何打印出来?

class TestProduct
{
    static void Main(string[] args)
    {
        // Assigning correct properties to the product
        Product p1 = new Product(1234567, "Cake", "Miscellaneous", 7.5, 150);
        Console.WriteLine(p1);
        Console.ReadLine();
    }
}

希望我的问题很清楚。

【问题讨论】:

  • 请一次只关注一个问题,这样更容易写出好的答案。在我看来,您不应该使用static,请问您为什么决定将列表设为静态但尝试从 instance 构造函数中设置它?
  • 好的,我已经通过删除“static”关键字解决了我的第一个问题。在我的代码中有点错过了。还是不知道另外两个怎么做。
  • 这是一个将多个问题放在一起的不幸后果,您不仅冒着得到多个答案的风险,而这些答案只能一起回答所有问题,而且当您开始删除问题时,您也有可能得到答案现在不再回答任何事情。请避免这样做。换句话说,发布 1 个问题,如果结果是错误的,请删除该问题(删除按钮)。不要编辑人们已经开始回答的内容。
  • 这是我的第一个问题,所以下次我会尽量让我的问题更具体。很抱歉这个问题。

标签: c#


【解决方案1】:

this.category 中删除this 限定符,因为您正在访问一个静态变量,根据定义该变量不能属于某个类的实例。

当然,这意味着您会遇到命名冲突,因为静态 category 无法与本地 category 区分开来 - 所以回退到在静态名称的开头使用下划线之类的命名约定变量 - _category.

您还应该重新考虑为什么将私有变量 category 设为静态 - 没有理由这样做。

[...] 将 Category 设置为 Miscellaneous

要解决您的主要问题 - 如果不编写一个采用单个字符串的新构造函数,就无法做到这一点(因为您无法静态定义或强制执行 List&lt;&gt; 的长度,您只能以编程方式检查)。一个不错的选择是将枚举用作suggested by @apk,然后如果没有传入值Miscellaneous,则从链式构造函数中抛出ArgumentOutOfRangeException但您甚至应该重新考虑该策略 - 如果值 必须Miscellaneous 则考虑默认为链式构造函数中的值,不允许传入任意值然后测试一个可能的正确值。

【讨论】:

  • 老实说,鉴于 OP 提供的信息很少,一个同样好的答案是删除 static 限定符。
  • @decPL 你是绝对正确的,特别是因为 OP 没有说明为什么他们想要它是静态的。
  • 他也可以使用 Product.category = category;
  • 确实我忘记从那里删除静电了。我已经解决了这个问题,并尝试解决其他问题。
  • @Rufat 我已经解决了你的主要问题。
【解决方案2】:

我假设您实际上并不希望它成为 static 变量 (this question might help),只要您在构造函数中接收它。也许您希望它是不可变的,这是完全不同的。

你可以这样定义构造函数。

public class Product
{
    private readonly List<string> _categories;

    public Product() : this(new List<string>() { "Miscellanous"})
    {

    }

    public Product(List<string> category)
    {
        _categories = category;
    }
}

或者这样

public class Product
{
    // other code
    public Product()
    {
         categories = new List<string>();
         categories.Add("Miscellanous");
    }
}

另外readonly 仅禁止更改对_categories 变量的引用。如果你希望内容不可变,那么你should have a look at other kind of data structures 或者干脆在代码中实现。

【讨论】:

  • 静态部分确实是上一次尝试留下的错误。非常感谢您的帮助和文章!
【解决方案3】:

如果您有一组固定的类别,则可以使用enum 来存储所有值。

public enum ProductCategory
{
    Electric,
    Household,
    Garden,
    Miscellaneous
}

你可以像这样创建一个默认构造函数:

public enum ProductCategory
{
    Electric,
    Household,
    Garden,
    Miscellaneous
}

public class Product
{

    public ProductCategory Category { get; }

    public Product(ProductCategory category)
    {
        this.Category = category;
    }

    public Product() : this(ProductCategory.Miscellaneous)
    {
    }

}

static void Main()
{
    Product p1 = new Product();
    Console.WriteLine(p1.Category); // output: Miscellaneous
    Console.ReadKey();
}

如果您仍想将类别存储在字符串中,则可以修改此示例。如果你想要一个固定的有效类别列表,你可以在构造函数中检查类别是否有效。

【讨论】:

  • 虽然我喜欢所有的答案,但这是一种存储设定数量的类别的好方法,而且效果很好。谢谢。
  • 所以“正确答案”不是真正回答您的问题,而是向您展示一种不同的方法?这个答案不回答问题中描述的问题(限定类型名称,默认构造函数)。而是提供了一个(好的,公平地说)解决方法?
  • 正如我所说,我应该使用数组而不是列表,但是我得到了另一种选择来解决我的问题。
【解决方案4】:

类别必须是“只读”

问题不在于它是只读的,您得到cannot be accessed with an instance reference, qualify it with a type name instead 的原因是您将该属性声明为静态。一个static property cannot be accessed as an instance property

在默认构造函数中我也不能通过它

是的,你可以,如果你真的传入你声明的类型。

public Product() : this("Miscellaneous") //You're trying to pass in a string
{
}

你能明白为什么你不能把那个字符串传递给你的基础构造函数吗?

public Product(List<string> category) //base constructor takes a List<string>
{
    //stuff
}

您可以创建一个实际采用字符串的基本构造函数:

public Product(string cat)
{
    //Validate that the category passed in is valid, I.E. in your list
    foreach (var item in category)
    {
        if(object.Equals(item, cat))
            break;
        if(object.Equals(item, category.Last()))
            throw new Exception("D'oh! Invalid category");
    }

    //do stuff
}

类似的东西。可能有更好的验证方法。或者只是将您的类别设为 Enum,然后使用 Enum.TryParse 之类的内容进行验证。

【讨论】:

  • 感谢您的帮助。我已经用 Enum 解决了这个问题。
  • 所以“正确答案”不是真正回答您的问题,而是向您展示一种不同的方法?这个答案不回答问题中描述的问题(限定类型名称,默认构造函数)。而是提供了一个(好的,公平地说)解决方法?
  • @Rufat - 请阅读how to ask 以供将来参考。因为你问的问题不是公认的答案真正给出答案的问题。
  • 对不起,如果这对你有什么伤害,但我是新来的,所以我会努力改进我的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
相关资源
最近更新 更多