c#4.0-限制在c#中使用结构
本文关键字:结构 c#4 | 更新日期: 2023-09-27 17:58:07
好的,假设我有一个这样的结构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; } }
}
现在,我想做的是作为类ABC中方法的结果返回结构A,比如:
Class ABC{
public A getStructA(){
//creation of Struct A
return a;
}
}
我不希望任何使用我的库的程序员(它将有Struct A和Class ABC以及其他东西)能够创建Struct A.的实例。
我希望创建它的唯一方法是从getStructA()方法返回。然后可以通过适当的getter访问这些值。
那么,有没有办法设置这样的限制?所以Structure不能在某个类之外实例化?使用C#、.Net 4.0。
谢谢你的帮助。
---编辑:----
添加一些关于我为什么要尝试实现这一点的细节:
- 我的ABC班有一些"状态",人们可以查询。此状态有2个字符串值,然后是一长串整数
- 程序员永远不需要创建"Status"的对象/实例,状态只能通过类的"getStatus()"函数返回
- 我不想将这3个字段拆分为不同的方法,为了获得它们,我调用了Windows API(p/invoke),它返回了所有3个字段的类似结构
- 如果我真的要将其拆分为3个方法而不使用结构,那么每次调用这3个方法中的一个时,我都必须缓存结果或从Windows API调用该方法
因此,我可以制作一个公共结构,如果程序员愿意,他们可以实例化它,这对他们来说是无用的,因为没有方法可以接受它作为参数。或者,我可以用这样一种方式构建库,即该结构(或者如果它更容易的话,可以将其更改为类)只能作为方法的返回获得。
如果"restricted"类型是一个结构,那么不,没有办法做到这一点。该结构必须至少与工厂方法一样公共,如果该结构是公共的,则可以使用其默认构造函数来构造它。然而,你可以这样做:
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;
}
...
现在您可以让您的库代码检查"valid"标志。A的实例只能由(1)可以调用内部构造函数的库内部方法生成,或者(2)由默认构造函数生成。你可以用有效的标志来区分它们。
许多人建议使用界面,但这有点毫无意义;使用结构的全部目的是获得值类型语义,然后将其装箱到接口中。你不妨先把它列为一门课。如果它将成为一个类,那么它当然有可能生成一个工厂方法;只需将类的所有actor设置为内部即可。
当然,我希望不用说,这些设备都不应该用于实现能够抵御完全可信用户攻击的代码。请记住,此系统是为了保护好用户免受坏代码的侵害,而不是保护好代码免受坏用户
创建一个公共接口,并使该类对调用它的类是私有的。
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();
然后随后所述CCD_ 9。和其他变量一样,functionResult
的行为是保存最后一个写入的东西。如果最后一个被写入的东西是最后一次调用doSomething()
的结果,那么它就会保存。如果最后写的是别的东西,它就会容纳别的东西。
请注意,与类字段或结构属性不同,结构字段只能通过写入来更改,或者通过使用结构赋值语句将一个结构实例中的所有字段与另一个结构的相应字段中的值写入来更改。从使用者的角度来看,只读结构属性没有这样的保证。结构可能碰巧实现了一个属性,使其以这种方式运行,但如果不检查该属性的代码,就无法知道它返回的值是否会受到某个可变对象的影响。