当前位置: 首页 > 编程语言 > C#

有没有办法从myFunc(newint{1,2,3}}中删除myFunc(1,2,3)?分享

时间:2023-04-10 21:13:35 C#

有没有办法删除myFunc(newint{1,2,3}}removemyFunc(1,2,3)?向所有C#向导提问。我有一个方法,称之为myFunc,它采用可变长度/类型参数列表。myFunc本身的参数签名是myFunc(paramsobject[]args),我在列表上使用反射(例如,将其视为有点像printf)。我想将myFunc(1,2,3)与myFunc(newint[]{1,2,3})myFunc(newint[]{1,2,3})。也就是说,在myFunc的主体内,我想枚举我的参数类型,并希望以{int,int,int}结束int[]。现在我得到后者:实际上,我无法区分这两种情况,它们都显示为int[]。我希望前者显示为obs[].length=3,obs[0]=1等。我原以为后者会显示为obs[]。length=1,whereobs[0]={int[3]}这可以做到吗,还是我问不可能?这样做:使用系统;类程序{staticvoidMain(string[]args){Console.WriteLine("Firstcall");富(1、2、3);Console.WriteLine("第二次通话");Foo(新整数[]{1,2,3});}staticvoidFoo(paramsobject[]values){foreach(objectxinvalues){控制台。WriteLine(x.GetType().Name);或者,如果使用DynamicObject,您可以使用动态类型来实现类似的结果:usingSystem;使用System.Dynamic;类程序{staticvoidMain(string[]args){dynamicd=newArgumentDumper();Console.WriteLine("第一次调用");d.Foo(1,2,3);Console.WriteLine("第二次通话");d.Bar(newint[]{1,2,3});}}classArgumentDumper:DynamicObject{publicoverrideboolTryInvokeMember(InvokeMemberBinderbinder,Object[]args,outObjectresult){result=null;foreach(args中的对象x){Console.WriteLine(x.GetType().Name);}返回真;}}两种解决方案的输出:第一调用Int32Int32Int32第二调用Int32[]现在给出上面的输出,不清楚你的问题从何而来…...虽然你给了Foo("1","2","3")vsFoo(newstring[]{"1","2","3"})那么它会是另一个-因为string[]与object[]兼容,但int[]不是好的,假设我们放弃了另一个您误认为是编译器错误的问题,但实际上解决了您的实际问题。首先,让我们试着说出真正的问题。这是我的镜头:序言:“varargs”方法是一种采用未指定数量的参数的方法。在C#中实现可变参数方法的标准方法是:voidM(T1t1,T2t2,paramsP[]p)也就是说,零个或多个必需参数后跟一个标记为“params”的数组。当调用这样的方法时,该方法将以其正常形式(不带参数)或扩展形式(带参数)应用。即,对voidM(paramsobject[]x){}形式M(1,2,3)的调用生成为M(newobject[]{1,2,3});因为它只适用于它的扩展形式。但是调用M(newobject[]{4,5,6});生成为M(newobject[]{4,5,6});不是M(newobject[]{newobject[]{4,5,6}});因为它以正常形式工作。C#支持引用类型元素数组的不安全数组协变。也就是说,即使试图将此类数组的第一个元素更改为非字符串,也会将string[]隐式转换为object[],这将产生运行时错误。问题是:我希望调用表单:M(newstring[]{"hello"});并且此方法仅适用于扩展形式:M(newobject[]{newstring[]{"hello"}});而不是正常形式:M((object[])(newstring[]{"hello"}));在C#中有没有一种方法可以实现可变方法,这些方法不会成为不安全的数组协方差总和优先以正常形式应用的方法的组合?回答是的,有一种方法,但您不会喜欢它。如果您打算将单个数组传递给它,最好使该方法不可变。Microsoft的C#实现支持一个未记录的扩展,允许在不使用params数组的情况下使用C风格的可变方法。此机制不适合一般用途,仅包含在CLR团队和其他编写互操作库的人员中,以便他们可以编写互操作代码,在C#和期望C样式可变方法的语言之间架起桥梁。我强烈建议不要尝试这样做。这样做的机制涉及使用未记录的__arglist关键字。基本草图是:publicstaticvoidM(__arglist){varargumentIterator=newArgIterator(__arglist);对象参数=TypedReference.ToObject(argumentIterator.GetNextArg());您可以使用参数迭代器的方法来迭代参数结构并获取所有参数。你可以使用超级魔法类型引用对象来获取参数的类型。使用这种技术甚至可以将对变量的引用作为参数传递,但我不推荐这样做。这种技术特别糟糕的是调用者需要说:M(__arglist(newstring[]{"hello"}));坦率地说,这在C#中看起来很粗糙。现在您明白了为什么最好完全放弃可变方法;只需让调用者传递一个数组并完成它即可。同样,我的建议是(1)您在任何情况下都不应尝试使用这些未记录的C#语言扩展,这些扩展旨在为CLR实现团队和互操作库作者提供便利,并且(2)您的Mutable方法应该只是丢弃;它们似乎不适合您的问题空间。不要与工具作斗争;选择不同的工具。是的,您可以检查参数长度并检查参数类型,请参阅此工作代码示例:classProgram{staticvoidMain(string[]args){myFunc(1,2,3);myFunc(newint[]{1,2,3});}staticvoidmyFunc(paramsobject[]args){if(args.Length==1&&(args[0]isint[])){//使用myFunc(newint[]{1,2,3});}else{//使用myFunc(1,2,3)或其他调用}}}您可以通过打破列表中的第一个元素并提供像这样的额外重载来完成此操作,例如:classFoo{publicintSum(){//普通情况return0;}publicintSum(inti){//单例情况returni;}publicintSum(inti,paramsint[]others){//例如Sum(1,2,3,4)returni+Sum(others);}publicintSum(int[]items){//例如Sum(newint[]{1,2,3,4});诠释我=0;foreach(intqinitems)i+=q;返回我;这在C#中是不可能的。C#将在编译时用第二个调用替换您的第一个调用。一种可能性是创建一个没有参数的重载并使其成为ref参数。这可能没有意义。如果您想根据输入更改行为,可以给第二个myFunc另一个名称。更新我现在明白你的问题了。你想要的是不可能的。如果唯一的参数是任何可以被解析为object[]的东西,就没有办法区分它。您需要一个替代解决方案,可能有一个由调用者创建的字典或数组来构建参数。事实证明存在一个真正的问题,它归结为C#进行类型推断的方式。请参阅其他主题的讨论以上是C#学习教程:是否有办法从myFunc(newint{1,2,3}}中删除myFunc(1,2,3)?如果对大家有帮助,请分享整个内容有用,需要了解更多C#学习教程,希望大家多多关注-本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除,如需转载请注明出处: