Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.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#_.net_Class_Struct - Fatal编程技术网

C# 在C中作为委托参数传递结构或类#

C# 在C中作为委托参数传递结构或类#,c#,.net,class,struct,C#,.net,Class,Struct,代码A: 公共类测试 { public struct TestValueArgs//struct通过浅拷贝传递 { 公共静态只读TestValueArgs Empty=新TestValueArgs(/*默认参数*/); 公共只读字符串名称; 公共只读int电话; 公共只读文件是活动的; 公共只读SomeClass用户信息; 公共只读测试发送器; //省略构造函数 } 公共事件行动一个或多个; } 代码B: public class Test { public struct TestVa

代码A:

公共类测试
{
public struct TestValueArgs//struct通过浅拷贝传递
{
公共静态只读TestValueArgs Empty=新TestValueArgs(/*默认参数*/);
公共只读字符串名称;
公共只读int电话;
公共只读文件是活动的;
公共只读SomeClass用户信息;
公共只读测试发送器;
//省略构造函数
}
公共事件行动一个或多个;
}
代码B:

public class Test
{
    public struct TestValueArgs // struct passed by shallow copy
    {
        public static readonly TestValueArgs Empty = new TestValueArgs(/*default parameters*/);

        public readonly string name;
        public readonly int phone;
        public readonly bool isActive;
        public readonly SomeClass userInfo;
        public readonly Test sender;

        // constructor omitted
    }

    public event Action<TestValueArgs> OnEventTriggered;
}
公共类测试
{
公共类TestClassArgs//class通过指针值传递
{
公共静态只读TestClassArgs Empty=新TestClassArgs(/*默认参数*/);
公共只读字符串名称;
公共只读int电话;
公共只读文件是活动的;
公共只读SomeClass用户信息;
公共只读测试发送器;
//省略构造函数
}
公共事件行动一个或多个;
}
代码C:

public class Test
{
    public class TestClassArgs // class passed by pointer value
    {
        public static readonly TestClassArgs Empty = new TestClassArgs (/*default parameters*/);

        public readonly string name;
        public readonly int phone;
        public readonly bool isActive;
        public readonly SomeClass userInfo;
        public readonly Test sender;

        // constructor omitted


    }

    public event Action<TestClassArgs> OnEventTriggered;
}
公共类测试
{
公共类TestReuseArgs//可重用
{
public static readonly TestReuseArgs Empty=新的TestReuseArgs(/*默认参数*/);
私有静态只读TestReuseArgs实例=新的TestReuseArgs(/*默认参数*/);
公共静态TestReuseArgs创建(/*参数*/)//必要时实现对象池系统
{
/*
覆盖现有实例
Instance.name=。。。;
Instance.phone=。。。;
...
*/
返回实例;
}
私有字符串名称;
私人int电话;
私人住宅是活跃的;
私有类用户信息;
专用测试发送器;
//消气剂性质省略
//构造函数已弃用
}
公共事件行动一个或多个;
}
现在,基于上面的代码块,我确实有一些问题:

  • 对于代码A,因为TestValueArgs是一个结构,所以在发出事件时,它应该作为传递给事件的每个侦听器的参数进行浅层复制。随着侦听器数量的增加或结构的大小的增加,复制整个结构的成本将变得巨大。此外,我们通常不知道有多少听众会听这个事件。那么,这种不稳定性是否是EventHandler的参数EventArgs是类而不是结构的原因呢
  • 对于代码B,每次尝试发出事件时都需要传入TestClassArgs的对象实例。对于到目前为止我看到的所有文档/示例,它们只是简单地分配一个新的EventArgs实例(在我的例子中是TestClassArgs)。我的猜测是,分配是好的,因为发出事件本身是一个不便宜的操作,所以当我们使用事件时,我们假设它们发出的频率不足以成为问题,从而降低了分配的频率。我说得对吗
  • 代码C比代码A和B好吗?因为它避免了卷影复制和频繁分配(如果有)。虽然我可以看出它不是线程安全的,并且实现对象池系统可能需要适度的工作量和精力,但我个人认为代码C是减少事件处理开销的最好方法。这是一个过早的优化(如果它确实优化了任何东西)
  • 我对EventHandler感到不舒服的原因是,对象o参数使委托的类型非常弱(不确定这是否是正确的术语),并且在我能够正确访问发送方之前,始终需要安全地执行强制转换。因此,我将其作为类字段发送者移动到arg容器中。.Net在EventHandler中具有对象类型参数是否有特定原因?还是仅仅为了一般目的

  • 我会小心地把时间花在这样的事情上。如果您想知道引擎盖下发生了什么以及事情是如何工作的,这很好,但是除非您真的需要提高代码的所有性能,否则只需创建类并使用只读属性即可。我怀疑你是否能测量出这种差异。但这只是MHO:)
    public class Test
    {
        public class TestReuseArgs // reusable
        {
            public static readonly TestReuseArgs Empty = new TestReuseArgs (/*default parameters*/);
            private static readonly TestReuseArgs Instance = new TestReuseArgs (/*default parameters*/);
            public static TestReuseArgs Create(/*parameters*/) // implement a object pooling system if necessary
            {
                /*
                overwrite existing Instance
                Instance.name = ...;
                Instance.phone = ...;
                ...
                */
                return Instance;
            }
    
            private string name;
            private int phone;
            private bool isActive;
            private SomeClass userInfo;
            private Test sender;
    
            // getter properties omitted
            // constructor deprecated
        }
    
        public event Action<TestReuseArgs> OnEventTriggered;
    }