访问修饰符和继承
本文关键字:继承 访问 | 更新日期: 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
,它将范围限制在给定的程序集。
如果将MyClass
和NewMyClass
放在同一个程序集中,并将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;
}
}
MyClass
的private
构造函数阻止任何人直接创建。
静态助手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);
}
}
}
}
但是,如果两个名称空间都在同一个程序集中,那么用户无论如何都可以实例化该类。