C#该委托必须有一个目标且仅有一个目标,使用【同步Invoke】代替【异步BeginInvoke】即可解决

81 篇文章 3 订阅
13 篇文章 0 订阅

在代理调用BeginInvoke(new AsyncCallback(callBack), null);时,会抛这个异常的原因是该代理变量代理了一个以上的方法.。

解决方案:

事件使用Invoke代替原来的BeginInvoke

因更新界面已经是BeginInvoke了,因此触发事件使用BeginInvoke可能会弹出【委托必须有一个目标且仅有一个目标】错误。

在线程中触发事件使用BeginInvoke,同时更新刷新界面也使用BeginInvoke就会出现这种问题。

出现Bug的相关源程序如下:

定义事件【事件是一种特殊的委托】

/// <summary>
        /// 刷新工单剩余数量:工单号:工单总数,已释放数,剩余数量
        /// </summary>
        static event Action<string, decimal, decimal, decimal> EventUpdateQuantity;

初始化方法时绑定事件

public FormWorkOrder()
        {
            InitializeComponent();
            //其他逻辑

            EventUpdateQuantity -= FrmWorkOrderConfig_EventUpdateQuantity;
            EventUpdateQuantity += FrmWorkOrderConfig_EventUpdateQuantity;            
        }

        /// <summary>
        /// 工单号:工单总数,已释放数,剩余数量
        /// </summary>
        /// <param name="workOrderPara"></param>
        /// <param name="totalQuantity"></param>
        /// <param name="releasedQuantity"></param>
        /// <param name="remainderQuantity"></param>
        private void FrmWorkOrderConfig_EventUpdateQuantity(string workOrderPara, decimal totalQuantity, decimal releasedQuantity, decimal remainderQuantity)
        {
            try
            {
                //异步刷新工单列表
                this.BeginInvoke(new Action(() =>
                {
                    for (int i = 0; i < dgvData.Rows.Count; i++)
                    {
                        string workOrder = Convert.ToString(dgvData["dgvcWorkOrder", i].Value);
                        if (!string.IsNullOrWhiteSpace(workOrder) && workOrder.Trim() == workOrderPara)
                        {
                            //如果类型代码不为空 和 模组PN码为空,就出错
                            dgvData["dgvcTotal", i].Value = totalQuantity;
                            dgvData["dgvcReleased", i].Value = releasedQuantity;
                            dgvData["dgvcRemainder", i].Value = remainderQuantity;
                            break;
                        }
                    }
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show($"当前工单刷新错误:{ex.Message}");
            }
        }

Load事件中开启一个线程,每个2秒就刷新工单剩余数量:

/// <summary>
        /// 刷新工单剩余数量,每隔60秒刷新一次
        /// </summary>
        private void RefreshWorkOrderQuantity()
        {
            int scanPeriodSecond = 2;//扫描周期默认2秒
            Task.Factory.StartNew(() =>
            {
                try
                {
                    while (isMonitor)
                    {
                        //读取所有工单信息
                        List<string> workOrderList = new List<string>();
                        for (int i = 0; i < dgvData.Rows.Count; i++)
                        {
                            string workOrder = Convert.ToString(dgvData["dgvcWorkOrder", i].Value);
                            if (!string.IsNullOrWhiteSpace(workOrder))
                            {
                                if (!workOrderList.Contains(workOrder.Trim()))
                                {
                                    workOrderList.Add(workOrder.Trim());
                                }
                            }
                        }

                        //获取每个工单对应的 工单总数,已释放数,剩余数量
                        for (int i = 0; i < workOrderList.Count; i++)
                        {
                            Tuple<string, decimal, decimal> tuple = GetWorkOrderQuantity(workOrderList[i]);
                            decimal remainderQuantity = tuple.Item2 - tuple.Item3;
                            if (EventUpdateQuantity != null)
                            {
                                //原来的代码 委托不能重新绑定,只能绑定一次
                                EventUpdateQuantity.BeginInvoke(workOrderList[i], tuple.Item2, tuple.Item3, remainderQuantity, null, null);
                                //EventUpdateQuantity.Invoke(workOrderList[i], tuple.Item2, tuple.Item3, remainderQuantity);
                            }
                        }
                        Thread.Sleep(scanPeriodSecond * 1000);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"出错:【{ex.Message}】", "错误");
                }
            });
        }

        /// <summary>
        /// 获取工单总数与已释放数
        /// </summary>
        /// <param name="workOrder"></param>
        /// <returns></returns>
        private Tuple<string, decimal, decimal> GetWorkOrderQuantity(string workOrder)
        {
            return ListWorkOrder.Find(tuple => tuple.Item1 == workOrder);
        }

运行的时候,界面不刷新工单数量,有时还会弹出【该委托必须有一个目标且仅有一个目标】

解决方案:将事件触发调用由【异步BeginInvoke】修改为【同步Invoke】。

新建窗体应用程序DelegateTestDemo,将默认的Form1重命名为FormWorkOrder。

窗体设计如图:

 窗体FormWorkOrder源程序如下【忽略设计器自动生成的代码】

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DelegateTestDemo
{
    public partial class FormWorkOrder : Form
    {
        /// <summary>
        /// 开启监控工单剩余数量,已释放数
        /// </summary>
        static bool isMonitor = false;
        /// <summary>
        /// 刷新工单剩余数量:工单号:工单总数,已释放数,剩余数量
        /// </summary>
        static event Action<string, decimal, decimal, decimal> EventUpdateQuantity;
        /// <summary>
        /// 工单列表:元组的第一个代表工单编号,第二个代表工单总数,第三代表已释放数
        /// </summary>
        static List<Tuple<string, decimal, decimal>> ListWorkOrder = new List<Tuple<string, decimal, decimal>>();
        public FormWorkOrder()
        {
            InitializeComponent();

            //改变DataGridview的列标题字体颜色
            dgvcWorkOrder.HeaderCell.Style = new DataGridViewCellStyle() { ForeColor = Color.Red };
            dgvcRemainder.HeaderCell.Style = new DataGridViewCellStyle() { ForeColor = Color.Red };
            this.dgvData.EnableHeadersVisualStyles = false;

            dgvcTotal.ReadOnly = true;
            dgvcReleased.ReadOnly = true;
            dgvcRemainder.ReadOnly = true;

            this.FormClosing += FormWorkOrder_FormClosing;

            EventUpdateQuantity -= FrmWorkOrderConfig_EventUpdateQuantity;
            EventUpdateQuantity += FrmWorkOrderConfig_EventUpdateQuantity;
            InitAllWorkOrder();
        }

        /// <summary>
        /// 关闭窗体前移除事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormWorkOrder_FormClosing(object sender, FormClosingEventArgs e)
        {
            isMonitor = false;
            EventUpdateQuantity -= FrmWorkOrderConfig_EventUpdateQuantity;
        }

        /// <summary>
        /// 初始化加载所有工单
        /// </summary>
        void InitAllWorkOrder()
        {
            ListWorkOrder = new List<Tuple<string, decimal, decimal>>();
            ListWorkOrder.Add(Tuple.Create("123456", 1000M, 200M));
            ListWorkOrder.Add(Tuple.Create("234567", 800M, 300M));
            ListWorkOrder.Add(Tuple.Create("345678", 700M, 256M));
            ListWorkOrder.Add(Tuple.Create("456789", 900M, 499M));

            dgvData.Rows.Clear();
            for (int i = 0; i < ListWorkOrder.Count; i++)
            {
                dgvData.Rows.Add(ListWorkOrder[i].Item1, ListWorkOrder[i].Item2, ListWorkOrder[i].Item3, ListWorkOrder[i].Item2 - ListWorkOrder[i].Item3);
            }
        }

        /// <summary>
        /// 工单号:工单总数,已释放数,剩余数量
        /// </summary>
        /// <param name="workOrderPara"></param>
        /// <param name="totalQuantity"></param>
        /// <param name="releasedQuantity"></param>
        /// <param name="remainderQuantity"></param>
        private void FrmWorkOrderConfig_EventUpdateQuantity(string workOrderPara, decimal totalQuantity, decimal releasedQuantity, decimal remainderQuantity)
        {
            try
            {
                //异步刷新工单列表
                this.BeginInvoke(new Action(() =>
                {
                    for (int i = 0; i < dgvData.Rows.Count; i++)
                    {
                        string workOrder = Convert.ToString(dgvData["dgvcWorkOrder", i].Value);
                        if (!string.IsNullOrWhiteSpace(workOrder) && workOrder.Trim() == workOrderPara)
                        {
                            //如果类型代码不为空 和 模组PN码为空,就出错
                            dgvData["dgvcTotal", i].Value = totalQuantity;
                            dgvData["dgvcReleased", i].Value = releasedQuantity;
                            dgvData["dgvcRemainder", i].Value = remainderQuantity;
                            break;
                        }
                    }
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show($"当前工单刷新错误:{ex.Message}");
            }
        }

        /// <summary>
        /// 窗体加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormWorkOrder_Load(object sender, EventArgs e)
        {
            isMonitor = true;
            RefreshWorkOrderQuantity();
        }

        /// <summary>
        /// 刷新工单剩余数量,每隔60秒刷新一次
        /// </summary>
        private void RefreshWorkOrderQuantity()
        {
            int scanPeriodSecond = 2;//扫描周期默认2秒
            Task.Factory.StartNew(() =>
            {
                try
                {
                    while (isMonitor)
                    {
                        //读取所有工单信息
                        List<string> workOrderList = new List<string>();
                        for (int i = 0; i < dgvData.Rows.Count; i++)
                        {
                            string workOrder = Convert.ToString(dgvData["dgvcWorkOrder", i].Value);
                            if (!string.IsNullOrWhiteSpace(workOrder))
                            {
                                if (!workOrderList.Contains(workOrder.Trim()))
                                {
                                    workOrderList.Add(workOrder.Trim());
                                }
                            }
                        }

                        //获取每个工单对应的 工单总数,已释放数,剩余数量
                        for (int i = 0; i < workOrderList.Count; i++)
                        {
                            Tuple<string, decimal, decimal> tuple = GetWorkOrderQuantity(workOrderList[i]);
                            decimal remainderQuantity = tuple.Item2 - tuple.Item3;
                            if (EventUpdateQuantity != null)
                            {
                                //原来的代码 委托不能重新绑定,只能绑定一次
                                //EventUpdateQuantity.BeginInvoke(workOrderList[i], tuple.Item2, tuple.Item3, remainderQuantity, null, null);
                                EventUpdateQuantity.Invoke(workOrderList[i], tuple.Item2, tuple.Item3, remainderQuantity);
                            }
                        }
                        Thread.Sleep(scanPeriodSecond * 1000);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"出错:【{ex.Message}】", "错误");
                }
            });
        }

        /// <summary>
        /// 获取工单总数与已释放数
        /// </summary>
        /// <param name="workOrder"></param>
        /// <returns></returns>
        private Tuple<string, decimal, decimal> GetWorkOrderQuantity(string workOrder)
        {
            return ListWorkOrder.Find(tuple => tuple.Item1 == workOrder);
        }

        /// <summary>
        /// 刷新按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            FormWorkOrder_Load(null, e);
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            isMonitor = false;
            int index = new Random().Next(0, ListWorkOrder.Count);
            if (ListWorkOrder[index].Item3 < ListWorkOrder[index].Item2)
            {
                ListWorkOrder[index] = Tuple.Create(ListWorkOrder[index].Item1, ListWorkOrder[index].Item2, ListWorkOrder[index].Item3 + 1);
            }

            FormWorkOrder_Load(null, e);
            isMonitor = true;
        }
    }
}

运行测试如图:

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【面试题库网整理 .net 面试题(附答案)(四)】 7. 某一密码使用K、L、M、N、O共5个字母,密码中的单词从左向右排列,密码单词必须遵循如下规则: (1) 密码单词的最小长度是两个字母,可以相同,也可以不同 (2) K不可能是单词的第一个字母 (3) 如果L出现,则出现次数不止一次 (4) M不能使最后一个也不能是倒数第二个字母 (5) K出现,则N就一定出现 (6) O如果是最后一个字母,则L一定出现 问题一:下列哪一个字母可以放在LO中的O后面,形成一个3个字母的密码单词? A) K B)L C) M D) N 答案:B 问题二:如果能得到的字母是K、L、M,那么能够形成的两个字母长的密码单词的总数是多少? A)1个 B)3个 C)6个 D)9个 答案:A 问题三:下列哪一个是单词密码? A) KLLN B) LOML C) MLLO D)NMKO 答案:C 8. 62-63=1 等式不成立,请移动一个数字(不可以移动减号和等于号),使得等式成立,如何移动? 答案:62移动成2的6次方 new有几种用法 第一种:new Class(); 第二种:覆盖方法 public new XXXX(){} 第三种:new 约束指定泛型类声明中的任何类型参数都必须有公共的无参数构造函数。 2.如何把一个array复制到arrayList里 foreach( object o in array )arrayList.Add(o); 3.datagrid.datasouse可以连接什么数据源 [dataset,datatable,dataview] dataset,datatable,dataview , IList 4.概述反射和序列化 反射:程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性 序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。 5.概述o/r mapping 的原理 利用反射,配置 将类于数据库表映射 7.用sealed修饰的类有什么特点 sealed 修饰符用于防止从所修饰的类派生出其它类。如果一个密封类被指定为其它类的基类,则会发生编译时错误。 密封类不能同时为抽象类。 sealed 修饰符主要用于防止非有意的派生,但是它还能促使某些运行时优化。具体说来,由于密封类永远不会有任何派生类,所以对密封类的实例的虚拟函数成员的调用可以转换为非虚拟调用来处理。 11.详述.NET里class和struct的异同! class:放在 ? struct放在? struct值传递 类与结构有很多相似之处:结构可以实现接口,并且可以具有与类相同的成员类型。然而,结构在几个重要方面不同于类:结构为值类型而不是引用类型,并且结构不支持继承。结构的值存储在“在堆栈上”或“内联”。细心的程序员有时可以通过聪明地使用结构来增强性能。 12.概述.NET里对 remoting 和 webservice 两项技术的理解和实际中的应用。 远程逻辑调用,remoing接口只能用在.net中 13.什么是code-behind技术 aspx and cs 14.概述三层结构体系 web/business/dataaccess 15.asp.net如何实现MVC模式,举例说明! web/business/dataaccess 2.什么是ASP.net中的用户控件 答:用户控件就是.ascx扩展名的东西喽,可以拖到不同的页面中调用,以节省代码.比如登陆可能在多个页面上有,就可以做成用户控件,但是有一个问题就是用户控件拖到不同级别的目录下后里面的图片等的相对路径会变得不准确,需要自已写方法调整. 3.什么叫应用程序域?什么是受管制的代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释? 答:装箱就是把值类型转成引用类型,从MS IL角度看好像是boxing,没记错的话是把值从堆栈转到堆中.拆箱相反,重载就是指一个方法名同,参数个数不同,返回值可以相同的方法.CLR是通用语言运行时,其它的不清楚. 4.列举一下你所了解的XML技术及其应用 答:XML可是好东西,保存配置,站与站之间的交流,WEB SERVICE都要用它. 5.值类型和引用类型的区别?写出C#的样例代码。 答:结构是值类型,类是引用类型,所以传结构就是值类型的应用啦,传对象或类就是引用类型的,这个不用多写了吧. 6.ADO.net中常用的对象有哪些?分别描述一下。 答:connection command sqladapter dataset datatable dataview等等.写不完了. 7.如何理解委托? 答:据说相当于函数指针,定义了委托就可以在不调用原方法名称的情况下调用那个方法. msdn2005中是这样解释的: 委托具有以下特点: 委托类似于 C++ 函数指针,但它是类型安全的。 委托允许将方法作为参数进行传递。 委托可用于定义回调方法。 委托可以链接在一起;例如,可以对一个事件调用多个方法。 方法不需要与委托签名精确匹配。有关更多信息,请参见协变和逆变。 C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。 【面试题库网整理 .net 面试题(附答案)(三)】 22.您要创建一个显示公司员工列表的应用程序。您使用一个DataGrid控件显示员工的列表。您打算修改这个控件以便在这个Grid的Footer显示员工合计数。请问您应该怎么做?( C? ) A.重写OnPreRender事件,当Grid的Footer行被创建时显示合计数。 B.重写OnItemCreated事件,当Grid的Footer行被创建时显示合计数。 C.重写OnItemDataBound事件,当Grid的Footer行被创建时显示合计数。 D. 重写OnLayout事件,当Grid的Footer行被创建时显示合计数。 23.您要创建ASP.NET应用程序用于运行AllWin公司内部的Web站点,这个应用程序包含了50个页面。您想要配置这个应用程序以便当发生一个HTTP代码错误时它可以显示一个自定义的错误页面给用户。您想要花最小的代价完成这些目标,您应该怎么做?(多选)( CD )   A.在这个应用程序的Global.asax文件中创建一个Application_Error过程去处理ASP.NET代码错误。   B.在这个应用程序的Web.config文件中创建一个applicationError节去处理ASP.NET代码错误。   C.在这个应用程序的Global.asax文件中创建一个CustomErrors事件去处理HTTP错误。   D.在这个应用程序的Web.config文件中创建一个CustomErrors节去处理HTTP错误。   E.在这个应用程序的每一页中添加一个Page指示符去处理ASP.NET 代码错误。   F. 在这个应用程序的每一页中添加一个Page指示符去处理ASP.NET HTTP错误。 24.您的公司有一个DB Server,名为AllWin,其上装了MS SQLSERVER 2000。现在需要您写一个数据库连接字符串,用以连接AllWin上SQL SERVER中的一个名为PubBase实例的Test库。请问,应该选择下面哪一个字符串?( B )   A. “Server=AllWin;Data Source=PubBase;Initial Catalog=Test;Integrated Security=SSPI”   B. “Server= AllWin;Data Source=PubBase;Database=Test;Integrated Security= SSPI”   C. “Data Source= AllWin \PubBase;Initial Category=PubBase;Integrated Security= SSPI”   D. “Data Source= AllWin \ PubBase;Database=Test;Integrated Security= SSPI” 25.您为AllWin公司创建了一个ASP.NET应用程序。这个应用程序调用一个 Xml Web Service。这个 Xml Web Service 将返回一个包含了公司雇员列表的DataSet对象。请问您该如何在这个程序中使用这个 Xml Web Service?( ? )   A.在“引用”对话框的.Net标签中选择 System.Web.Services.dll。   B.在“Web引用”对话框中输入这个 XML Web service 的地址。   C.在您的 Global.asax.cs 中添加一条 using 语句并指定这个 XML Web service 的地址。   D.在您的 Global.asax.cs 中写一个事件处理器导入这个 Xml Web Service 相应的 .wsdl 和 .disco 文件。 26.您要创建一个ASP.NET应用程序在DataGrid控件中显示一个经过排序的列表。产品数据被存放于一个名为PubBase的Microsoft SQL Server 数据库。每个产品的主键是ProductID,Numeric型并且每个产品有一个字母描述字段,名为ProductName。您使用一个SqlDataAdapter对象和一个SqlCommand对象通过调用一个存储过程从数据库中获取产品数据。您将SqlCommand对象的CommandType属性设置为CommandType.StoredProcedure,并将它的CommandText属性设置为procProductList。您成功的获取了一个DataTable对象,其中是已经按ProductID降序排列的产品列表。您打算显示以相反的字母顺序排列的ProductName,请问该怎么做? ( B )   A. 将SqlCommand对象的CommandType属性修改为CommandType.Text,将CommandText属性修改为”SELECT * FROM procProductList ORDER BY ProductName DESC”。然后将这个DataTable对象绑定到DataGrid控件。   B. 创建一个基于这个DataTable对象的新的DataView并将这个DataView的Sort属性设置为“ProductName DESC”。然后将这个DataView对象绑定到DataGrid控件。   C. 将DataGrid控件的AllowSorting属性设置为True,并将DataGridColumn的SortExpression属性设置为 “ProductName DESC”.以显示ProductName。然后将这个DataTable对象绑定到DataGrid控件。   D. 将DataTable对象的DisplayExpression属性设置为 “ORDER BY ProductName DESC”.。然后将这个DataTable对象绑定到DataGrid控件。 76.C#代码实现,确保windows程序只有一个实例(instance) ///<summary> ///应用程序的主入口点。 ///</summary> [STAThread] staticvoid Main() { //防止程序多次运行 if(!OneInstance.IsFirst("GetPayInfo")) { MessageBox.Show ("警告:程序正在运行中! 请不要重复打开程序!可在右下角系统栏找到!","程序错误提示:",MessageBoxButtons.OK,MessageBoxIcon.Stop); return; } Application.Run(new Form1()); } // ******************* 防止程序多次执行 ************************** publicabstractclass OneInstance { ///<summary> ///判断程序是否正在运行 ///</summary> ///<param name="appId">程序名称</param> ///<returns>如果程序是第一次运行返回True,否则返回False</returns> publicstaticbool IsFirst(string appId) { bool ret=false; if(OpenMutex(0x1F0001,0,appId)==IntPtr.Zero) { CreateMutex(IntPtr.Zero,0,appId); ret=true; } return ret; } [DllImport("Kernel32.dll",CharSet=CharSet.Auto)] privatestaticextern IntPtr OpenMutex( uint dwDesiredAccess, // access int bInheritHandle, // inheritance option string lpName // object name ); [DllImport("Kernel32.dll",CharSet=CharSet.Auto)] privatestaticextern IntPtr CreateMutex( IntPtr lpMutexAttributes, // SD int bInitialOwner, // initial owner string lpName // object name ); } 【面试题库网整理 .net 面试题(附答案)(二)】 8.以下代码段中能否编译通过?请给出理由。 try { } catch(FileNotFoundException e1) { } catch(Exception e2) { } catch(IOException e3) { } catch { } 9.对于一个实现了IDisposable接口的类,以下哪些项可以执行与释放或重置非托管资源相关的应用程序定义的任务?(多选) ( ABC ) A.Close B.DisposeC.Finalize D.using E.Quit 10.Net依赖以下哪项技术实现跨语言互用性?( C ) A.CLR B.CTS C.CLS D.CTT 11.请问: String类与StringBuilder类有什么区别?为什么在.Net类库中要同时存在这2个类?(简答) 如果要操作一个不断增长的字符串,尽量不用String类,改用StringBuilder类。两个类的工作原理不同:String类是一种传统的修改字符串的方式,它确实可以完成把一个字符串添加到另一个字符串上的工作没错,但是在.NET框架下,这个操作实在是划不来。因为系统先是把两个字符串写入内存,接着删除原来的String对象,然后创建一个String对象,并读取内存中的数据赋给该对象。这一来二去的,耗了不少时间。而使用System.Text命名空间下面的StringBuilder类就不是这样了,它提供的Append方法,能够在已有对象的原地进行字符串的修改,简单而且直接。当然,一般情况下觉察不到这二者效率的差异,但如果你要对某个字符串进行大量的添加操作,那么StringBuilder类所耗费的时间和String类简直不是一个数量级的。 12.以下哪个类是int的基类?( ) A.Int32 B.Object C.ValueType D.Int16 二、C# 部分* 13.以下哪些可以作为接口成员? (多选) ( ABDE ) A.方法B.属性C.字段D.事件E.索引器 F.构造函数G.析构函数 14.以下关于ref和out的描述哪些项是正确的?(多选) ( ACD ) A.使用ref参数,传递到ref参数的参数必须最先初始化。 B.使用out参数,传递到out参数的参数必须最先初始化。 C.使用ref参数,必须将参数作为ref参数显式传递到方法。 D.使用out参数,必须将参数作为out参数显式传递到方法。 15.“访问范围限定于此程序或那些由它所属的类派生的类型”是对以下哪个成员可访问性含义的正确描述?( B ) A.public B.protected C.internal D.protected internal 16.class Class1 { private static int count = 0; static Class1() { count++; } public Class1() { count++; } } Class1 o1 = new Class1(); Class1 o2 = new Class1(); 请问,o1.Count的值是多少?( C ) A.1 B.2 C.3 D.4 17.abstract class BaseClass { public virtual void MethodA() { } public virtual void MethodB() { } } class Class1: BaseClass { public void MethodA(string arg) { } public override void MethodB() { } } class Class2: Class1 { new public void MethodB() { } } class MainClass { public static void Main(string[] args) { Class2 o = new Class2(); Console.WriteLine(o.MethodA()); } } 请问,o.MethodA调用的是: ( A ) A.BaseClass.MethodAB.Class2.MethodA C.Class1.MethodAD.都不是 【.net 面试题系列文章一(附答案)】 1 (1)面向对象的语言具有__继承性_性、_封装性_性、_多态性 性。 (2)能用foreach遍历访问的对象需要实现 _ IEnumerable 接口或声明_ GetEnumerator 方法的类型。1.c#中的三元运算符是__?:__ 2.当整数a赋值给一个object对象时,整数a将会被__装箱___? 3.类成员有__3__种可访问形式? 4.public static const int A=1;这段代码有错误么?是什么? const成员都是static所以应该去掉static 5.float f=-123.567F; int i=(int)f; i的值现在是_-123____? 6.利用operator声明且声明了==,有什么错误么? 要同时修改Equale和GetHash() ? 重载了"==" 就必须重载 "!=" 7.委托声明的关键字是___ delegate ___? 8.用sealed修饰的类有什么特点?不可被继承 9.在Asp.net中所有的自定义用户控件都必须继承自_ System.Web.UI.UserControl _______? 10.在.Net中所有可序列化的类都被标记为__[serializable]___? 11.在.Net托管代码中我们不用担心内存漏洞,这是因为有了_ gC __? 12.下面的代码中有什么错误吗?_ abstract override 是不可以一起修饰______ using System; class A { public virtual void F(){ Console.WriteLine("A.F"); } } abstract class B:A { public abstract override void F(); } 13.当类T只声明了私有实例构造函数时,则在T的程序文本外部,_不可以_(可以 or 不可以)从T派生出新的类,_不可以_(可以 or 不可以)直接创建T的任何实例。 14.下面这段代码有错误么?case():不行 default; switch (i){ case(): CaseZero(); break; case 1: CaseOne(); break; case 2: dufault; CaseTwo(); break; } 15.在.Net中,类System.Web.UI.Page 可以被继承么?可以

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值