Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 限制在C中使用结构#_C#_C# 4.0_Data Structures_Struct - Fatal编程技术网

C# 限制在C中使用结构#

C# 限制在C中使用结构#,c#,c#-4.0,data-structures,struct,C#,C# 4.0,Data Structures,Struct,假设我有一个这样的结构: 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

假设我有一个这样的结构:

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; } }
}
Class ABC{
    public A getStructA(){
        //creation of Struct A
        return a;
    }
}
现在我想做的是,返回结构A作为ABC类中方法的结果,如下所示:

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; } }
}
Class ABC{
    public A getStructA(){
        //creation of Struct A
        return a;
    }
}
我不希望任何使用我的库(其中将有Struct A和Class ABC以及其他东西)的程序员能够创建Struct A的实例。
我希望创建它的唯一方法是作为getStructA()方法的返回。然后可以通过适当的getter访问这些值

那么有没有办法设置这样的限制?所以结构不能在某个类之外实例化?使用C#,.Net4.0

谢谢你的帮助

---编辑:----
要详细说明我为什么要实现这一目标,请执行以下操作:

  • 我的班级ABC有一些个人可以查询的“状态”。此状态有2个字符串值,然后是一长串整数
  • 程序员永远不需要创建“Status”的对象/实例,状态只能由类的“getStatus()”函数返回
  • 我不想将这3个字段拆分为不同的方法,为了获得它们,我调用了WindowsAPI(p/invoke),它会返回与所有3个字段相似的结构
  • 如果我真的要将它拆分为3个方法而不使用结构,那么每次调用这3个方法中的一个时,我要么缓存结果,要么从Windows API调用该方法

因此,我可以创建一个公共结构,程序员可以根据需要实例化它,这对他们来说是无用的,因为没有方法可以接受它作为参数。或者我可以这样构造库:这个结构(或者如果它使事情更容易的话,可以将它更改为类)只能作为方法的返回来获取。

创建一个公共接口,并使类对调用它的类私有

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; } }
    }
}
如果“restricted”类型是一个struct,那么就没有办法了。该结构必须至少与工厂方法一样公开,如果该结构是公开的,则可以使用其默认构造函数构造它。但是,您可以这样做:

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”标志。只能(1)通过库内部可调用内部构造函数的方法或(2)通过默认构造函数创建实例。您可以使用有效的标志来区分它们

很多人建议使用界面,但这有点毫无意义;使用结构的全部要点是获取值类型语义,然后将其装箱到接口中。你不妨先把它列为一门课。如果它将成为一个类,那么当然可以创建一个工厂方法;只需将类的所有构造函数都设置为内部


当然,我希望不用说,这些工具都不应该用于实现能够抵抗完全信任用户攻击的代码。记住,这个系统是为了保护好的用户不受坏代码的影响,而不是保护好的代码不受坏的用户的影响。没有任何东西可以阻止完全受信任的用户代码通过反射调用库中他们想要的任何私有方法,或者用不安全的代码更改结构内部的位

你到底关心什么?结构基本上是用管道胶带粘在一起的场的集合。由于struct赋值将所有字段从一个struct实例复制到另一个struct实例,在所讨论的struct类型的控制之外,struct强制执行任何类型的不变量的能力非常有限,特别是在多线程代码中(除非一个结构正好是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 assignment语句将一个结构实例中的所有字段与另一个结构实例的相应字段中的值一起写入来更改。从使用者的角度看,只读结构属性没有这样的保证。一个结构可能碰巧实现了一个属性以实现这种行为,但是w