【问题标题】:Internal and external interfaces and collections内部和外部接口和集合
【发布时间】:2009-04-06 08:16:45
【问题描述】:

实现以下内容的最佳方式是什么?

我有一个实现接口的对象集合,在内部我希望能够公开 set 并获取属性,而外部只能获取。

这是我想要的那种东西的一个例子...... 这不会编译。

public interface ITable
{
   string Name { get; }
}

internal interface IInternalTable 
{
   string Name { get; set; }
}

internal class Table : ITable, IInternalTable
{
   public string Name { get; set; }
   public string ITable.Name { get { return Name; } }
}

public class Database
{
    private List<IInternalTable> tables;

    public List<ITable>
    {
       get { return this.tables; }
    }
}

【问题讨论】:

    标签: c# inheritance interface


    【解决方案1】:

    使用这个:

    public interface ITable
    {
        string Name { get; }
    }
    
    public class Table : ITable
    {
        public string Name { get; internal set; }
    }
    
    public class Database
    {
        public List<ITable> Tables { get; private set; }
    }
    

    注意:在 get 或 set 访问器上使用的可访问性修饰符只能限制可见性而不是增加可见性。

    【讨论】:

    • 如果访问“名称”的代码在同一个程序集中,这将无济于事,因为“内部”就像程序集中的“公共”。
    • @scraimer:这就是 OP 想要的:“内部 [...] 设置和获取 [...] 外部只能获取。”
    • @Richard...嗯,我想我误解了“内部”不是“内部”关键字,而是“内部到类数据库”。
    【解决方案2】:

    如果 Table 隐式实现 IInternalTable,并且 IInternalTable 是内部的,那么这些方法将只能在内部访问(因为只有内部代码才能使用 IInternalTable:

    public interface ITable
    {
       string Name { get; }
    }
    
    internal interface IInternalTable 
    {
       string Name { get; set; }
    }
    
    public class Table : ITable, IInternalTable
    {
       public string Name { get; set; }
       string ITable.Name { get { return Name; } }
    }
    
    public class Database
    {
        private List<Table> tables;
    
        public List<Table> Tables
        {
           get { return this.tables; }
        }
    }
    

    (现在还公开了 Table 类型以避免缺乏协方差的问题...这也可以通过 Database.Tables 返回一个副本并具有不同的内部唯一属性来解决。)

    【讨论】:

      【解决方案3】:

      它不会编译,因为 IInternalTable 和 ITable 之间没有转换。解决方案就像 Koistya Navin 建议的那样:

      public class Table {
          public string Name {get; internal set; }
      }
      
      public class Database {
          public IList<Table> Tables { get; private set;}
      
          public Database(){
              this.Tables = new List<Table>();
          }
      }
      

      【讨论】:

        【解决方案4】:

        这是代表您的域模型的类中的常见需求,您希望您的对象具有公开公开的 ID 只读属性,该属性必须在内部设置。我过去使用的一个解决方案是使用方法作为 setter:

        public interface ITable
        {
            string Name { get; }
        }
        
        internal interface ITableInternal
        {
           void SetName(string value);
        }
        
        public class Table : ITable, ITableInternal
        {
            public string Name { get; }
        
            public void SetName(string value)
            {
               // Input validation
        
               this.Name = value;
            }
        }
        
        public class Database
        {
            public Table CreateTable()
            {
                Table instance = new Table();
                ((ITableInternal)instance).SetName("tableName");
        
                return table;
            }    
        }
        

        【讨论】:

        • 这可能对 Java 有好处,但 .Net 提供了更好的属性解决方案,为其访问者提供了不同的保护级别。
        • 我同意。如果使用 C# 1.0 以 .NET Framework 1.0/1.1 为目标,我的解决方案也可以很好地工作,因为 C# 2.0 可以为属性的 getter 和 setter 指定不同的访问修饰符。
        【解决方案5】:

        实际上,我建议将 setter-interface 完全隐藏为私有接口:

        public interface ITable
        {
           string Name { get; }
        }
        
        public class Database
        {
        
            private interface IInternalTable 
            {
               string Name { get; set; }
            }
        
            private class Table : ITable, IInternalTable
            {
                public string Name { get; set; }
                string ITable.Name { get { return Name; } }
            }
        
            private List<IInternalTable> tables;
        
            public List<ITable> Tables
            {
               get { return this.tables; }
            }
        }
        

        这样,Database 以外的任何人都不能修改Database.Tables 中的项目。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-30
          • 1970-01-01
          • 2022-08-12
          相关资源
          最近更新 更多