访问器必须比属性或索引器更加严格限制。

37

我有以下的类:

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

namespace Framework
{
    public class OracleProvider
    {
        private OdbcConnection db { get; private set; }
        private String dbUsername = Settings.Default.Username;
        private String dbPassword = Settings.Default.Password;

        public OracleProvider()
        {
            connect();
        }

        public void connect()
        { 
            db = new OdbcConnection("Driver={Microsoft ODBC for Oracle};Server=CTIR; UID="+dbUsername+";PWD="+dbPassword+";");    
        }        
    }
}

现在我遇到了以下错误:

错误11: 'Framework.OracleProvider.db.set' 访问器的可访问性修饰符必须比属性或索引器 'Framework.OracleProvider.db' 更加限制

我看了一些类似的问题,但没有真正找到答案。

有人能解释一下这是为什么吗?我真的想学习。

2个回答

57

这是问题:

private OdbcConnection db { get; private set; }

假设您确实希望getter和setter都是private的,则应该这样写:

private OdbcConnection db { get; set; }

该属性的可访问性为private,因此setter已经是私有的(private)private

或者,如果您想要getter是非private的,同时setter是private的,您需要指定其他修饰符,例如:

internal OdbcConnection db { get; set; }

基本上,如果您要在属性的get;set;部分指定访问修饰符,则必须比它本来应该更加严格。

引用自C#规范的第10.7.2节:

访问器修饰符必须声明一个比属性或索引器本身声明的访问级别更为严格的可访问性。 准确地说:

  • 如果属性或索引器声明了public的访问级别,则访问器修饰符可以是protected internalinternalprotectedprivate
  • 如果属性或索引器声明了protected internal的访问级别,则访问器修饰符可以是internalprotectedprivate
  • 如果属性或索引器声明了internalprotected的访问级别,则访问器修饰符必须是private
  • 如果属性或索引器声明了private的访问级别,则不能使用访问器修饰符

(顺便说一句,如果读写都是私有的,最好只使用字段。使用属性的大多数好处只有在超出当前类范围时才存在。如果您仍然将其保留为属性,请考虑重命名以遵循常规 .NET 命名约定。)


一个常见的模式是将setter设置为私有,但getter设置为公共/受保护,以使属性只读。为了完整起见,可能值得将此添加到答案中。 - Charleh
是的,我的评论花了大约5分钟才发布,而那时你已经更新了 :) - Charleh
我是一名Java开发者,最初什么是内部的,它与私有、受保护和公共有什么区别? - Marc Rasmussen
@MarcRasmussen:那是一个不同的问题 - 最好先进行一些研究来回答 :) (搜索“msdn internal c#”,您可能会得到答案。) - Jon Skeet
1
@Ecchi-Alex:不,它比“internal”更少限制。“访问仅限于此程序或从此类派生的类”。这是并集,而不是交集。(在C#7中可能会有一个新的修饰符组合来表示交集。) - Jon Skeet
显示剩余5条评论

8

好的,错误信息提供了所有所需的信息:

可访问性修饰符 ... 访问器必须比属性更具限制性 ...

  private OdbcConnection db { // <- property as whole is "private"
    get; 
    private set; // <- accessor (set) is explictly declared as "private" 
  }

所以你可以选择其中任意一种方法。
  // property as a whole is "public", but "set" accessor is "private"
  // and so the accessor is more restrictive than the property
  public OdbcConnection db { // <- property as whole is "public"
    get; 
    private set; // <- accessor is "private" (more restrictive than "public")
  }

或者

  private OdbcConnection db { 
    get; 
    set; // <- just don't declare accessor modifier
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接