访问修饰符和继承

本文关键字:继承 访问 | 更新日期: 2023-09-27 18:19:39

我试图让一个类只允许在命名空间范围内使用new关键字初始化。虽然我需要能够使用它的type示例

namespace MyNameSpace {
   class MyClass {
      public string Name { get; set; }
   }
   class NewMyClass {
       MyClass cls = new MyClass();
       cls.Name = "My Name";
   } 
} 

但在Program.cs上,我希望用户只能执行以下操作。

NewMyClass myC = new NewMyClass();
List<MyClass> myList = myC.method();
foreach(MyClass a in myList){
    Console.WriteLine(a.property);
} 

正如你所看到的,我希望他们将其用作数据类型,因为这将是它需要的列表类型。但我不希望用户在MyClass中设置Name,也不能调用new MyClass。我已经尝试将MyClass制作成一个接口,但我需要创建新的实例来存储在List中。

我也尝试过设置private set,这样只有NewMyClass才能设置它们,但这也不起作用。我已经读了一段时间了,我太困了!

我希望用户能够做什么~!

List<MyClass> //use as a datatype
Console.WriteLine(a.property); //call the property from the list

我不希望用户做什么!

new MyClass();
a.property = "Other Name" //set the value.

原因

用户没有理由调用MyClass,只有NewMyClass应该调用它。用户也没有理由将值分配给MyClass中的任何属性。我之所以使用类,是因为有人告诉我不要使用struct,这还可以,因为到目前为止我喜欢类方法的多功能性。但我需要从用户那里限制很多。

如果我错了,请告诉我,我是C#的新手,所以请不要害怕告诉我你会走哪条路,为什么,这样我就能理解你的推理。

思考的第二步

返回结构方法。我现在有

internal struct MyClass {
    public string Name {get; set;}
}

我喜欢的是,当我做时

MyClass cls = new MyClass();

它会发出警告,表明cls已分配但从未使用过。但当我们进行时

cls.Name = "google";

那个警告消失了,那个失败了,我不希望用户设置,但只有我的主类才能设置。

访问修饰符和继承

您不能限制namespace的访问。最接近您要查找的访问修饰符是internal,它将范围限制在给定的程序集。

如果将MyClassNewMyClass放在同一个程序集中,并将MyClass构造函数的访问修饰符设置为internal,那么您就可以找到解决方案了。

参考:https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx

您需要将'MyClass'设为公共,但它是'internal'成员。当然,只有当这些类在单独的程序集中时,"internal"才有效。

namespace MyNameSpace {
   public class MyClass {
       internal string Name { get; set; }
   }
   public class NewMyClass {
       MyClass cls = new MyClass();
       cls.Name = "My Name";
   } 
} 

虽然很难将创建限制为不在继承链中的一个类型(由于缺乏所需的可访问性级别),但可以使用嵌套类型。

class NewMyClass {
  private static Func<MyClass> create = null;
  public class MyClass {
    public static void Init() { NewMyClass.create = ()=> new MyClass();}
    private MyClass(){ }
    public string Name { get; set; }
  }
  public MyClass Method(){
    MyClass.Init(); 
    MyClass cls = create();
    cls.Name = "My Name";
    return cls;
  }
} 

MyClassprivate构造函数阻止任何人直接创建。

静态助手MyClass.Init()让它的外部类初始化私有委托来创建实例。嵌套类可以设置外部类的私有委托,因此两者必须合作才能实现所需的保护。

请注意,更合理的方法是将MyClass抽象化(或接口化),并在NewMyClass中提供private实现——您可能会发现这种方法也更容易测试。

如果您可以像Glenn已经指出的那样,在单独的程序集中将其分离,那将是最好的。然后你需要一个接口&工厂方法。

此外,我试图更改您的程序,使其使用接口-

    namespace MyNameSpace {

       public interface IMyClass
        {
            string Name { get; }
        }
       internal class MyClass : IMyClass  {
          public string Name { get; internal set; }
       }
       class NewMyClass {

           private IMyClass Init(string name)
           {
               MyClass cls = new MyClass();
               cls.Name = name;
               return cls;
           }
         public List<IMyClass> method()
           {
              var collection = new List<IMyClass>();
              collection.Add(Init("1st Sample"));
              collection.Add(Init("2nd Sample"));
              return collection;
           }
       } 
    }
    namespace UserNameSpace
    {
        public class Prog
        {
            public static void Func()
            {
                NewMyClass myC = new NewMyClass();
                List<IMyClass> myList = myC.method();
                foreach (IMyClass a in myList)
                {
                    Console.WriteLine(a.Name);
                }
            }
        }
    }

但是,如果两个名称空间都在同一个程序集中,那么用户无论如何都可以实例化该类。