[英]Restricting use of a structure in C#
好吧,让我说我有一个像这样的结构A:
Struct A{
private String _SomeText;
private int _SomeValue;
public A(String someText, int SomeValue) { /*.. set the initial values..*/ }
public String SomeText{ get { return _SomeText; } }
public int SomeValue{ get { return _SomeValue; } }
}
现在我想要做的是返回结构A作为类ABC中的方法的结果,如下所示:
Class ABC{
public A getStructA(){
//creation of Struct A
return a;
}
}
我不希望任何程序员使用我的库(它将具有Struct A和Class ABC以及更多东西)来创建Struct A的实例。
我希望创建它的唯一方法是从getStructA()方法返回。 然后可以通过适当的getter访问这些值。
那么有什么方法可以设置这样的限制吗? 那么一个结构不能在某个类之外实例化? 使用C#,。Net4.0。
谢谢你的帮助。
- -编辑: - -
要添加一些有关我为什么要尝试实现此目的的详细信息:
所以我可以创建一个公共结构,程序员可以根据需要实例化它,这对他们来说没用,因为没有方法可以接受它作为参数。 或者我可以以这样的方式构造库:只有从方法返回时,才能获得此结构(或者如果它使事情变得更容易将其更改为类)。
如果“受限制”类型是结构,那么不,没有办法做到这一点。 结构必须至少与工厂方法一样公开,如果结构是公共的,那么它可以使用其默认构造函数构造。 但是,您可以这样做:
public struct A
{
private string s;
private int i;
internal bool valid;
internal A(string s, int i)
{
this.s = s;
this.i = i;
this.valid = true;
}
...
现在您可以让您的库代码检查“有效”标志。 A的实例只能通过(1)通过库内部可以调用内部构造函数的方法或(2)通过默认构造函数来实现。 您可以使用有效标志区分它们。
很多人建议使用界面,但这有点无意义; 使用结构的全部意义在于获取值类型语义,然后将其装入接口。 你最好还是让它成为一个班级。 如果它将成为一个类,那么肯定可以制造工厂方法; 只是让班上的所有人都在内部。
当然,我希望不言而喻,不应该使用这些设备来实现能够抵抗完全信任用户攻击的代码。 请记住,这个系统可以保护好用户免受不良代码的侵害,而不是来自坏用户的 好代码 。 没有任何东西可以阻止完全受信任的用户代码通过反射调用它们在库中所需的任何私有方法,或者就此而言,使用不安全的代码更改结构中的位。
创建一个公共接口,并使该类对调用它的类是私有的。
public ISpecialReturnType
{
String SomeText{ get; }
int SomeValue{ get; }
}
class ABC{
public ISpecialReturnType getStructA(){
A a = //Get a value for a;
return a;
}
private struct A : ISpecialReturnType
{
private String _SomeText;
private int _SomeValue;
public A(String someText, int SomeValue) { /*.. set the initial values..*/ }
public String SomeText{ get { return _SomeText; } }
public int SomeValue{ get { return _SomeValue; } }
}
}
你究竟关心什么? 结构基本上是用胶带粘在一起的字段的集合。 由于结构赋值将所有字段从一个结构实例复制到另一个结构实例,在所讨论的结构类型的控制之外,结构体强制执行任何类型的不变量的能力非常有限,特别是在多线程代码中(除非结构正是如此) 1,2或4个字节,想要创建包含从两个不同实例复制的数据混合的实例的代码可以非常容易地完成,并且结构无法阻止它。
如果要确保您的方法不接受除类型在内部生成的类型之外的任何类型的实例,则应使用仅具有internal
或private
构造函数的类。 如果您这样做,您可以确定您正在获取自己生成的实例。
编辑根据修订版,我不认为所要求的限制类型是必要的或特别有用。 这听起来像是根本上希望将一堆值粘在一起并将它们存储到调用者所持有的一组固定变量中。 如果您简单地声明一个结构:
public struct QueryResult {
public ExecutionDuration as Timespan;
public CompletionTime as DateTime;
public ReturnedMessage as String;
}
宣言:
QueryResult foo;
将有效地创建三个变量,名为foo.ExecutionDuration
, foo.CompletionTime
和foo.ReturnedMessage
。 该声明:
foo = queryPerformer.performQuery(...);
将根据函数的结果设置这三个变量的值 - 基本上相当于:
{
var temp = queryPerformer.performQuery(...);
foo.ExecutionDuration = temp.ExecutionDuration
foo.CompletionTime = temp.CompletionTime;
foo.ReturnedMessage = temp.ReturnedMessage;
}
什么都不会阻止用户代码用这三个变量做任何想做的事情,但那又怎样呢? 如果用户代码决定说什么原因foo.ReturnedMessage = "George";
然后foo.ReturnedMessage
将等于George
。 如果代码说的话,情况确实没有什么不同:
int functionResult = doSomething();
然后再说functionResult = 43;
。 与任何其他变量一样, functionResult
的行为是保存写入它的最后一件事。 如果写入的最后一件事是上次调用doSomething()
,那就是它将保留的内容。 如果最后写的东西是别的东西,那么它将保留其他东西。
请注意,结构字段与类字段或结构属性不同, 只能通过写入来更改,或者通过使用结构赋值语句来编写一个结构实例中的所有字段,并使用另一个结构实例的相应字段中的值。 从消费者的角度来看,只读struct属性没有这样的保证。 结构可能碰巧实现一个属性来表现那种方式,但是如果不检查属性的代码,就无法知道它返回的值是否会受到某个可变对象的影响。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.