gpt4 book ai didi

c# - System.Collections.Generic.List.ToArray() 和 System.Linq.Enumerable.ToArray() 之间的区别?

转载 作者:行者123 更新时间:2023-11-30 18:00:05 25 4
gpt4 key购买 nike

我最近在使用某种网络方法时遇到了很多问题:

void CheckGfiHelpdesks(string ticket, GfiCheck[] newHelpdeskChecks, GfiCheck[] otherChecks)

我一直在用这段代码调用那个方法:

List<GfiCheck> newFailedChecks = new List<GfiCheck>();

List<GfiCheck> otherFailedChecks = new List<GfiCheck>();

//do some work, create new GfiCheck items, fill the lists

Webclient.CheckGfiHelpdesks(Ticket, newFailedChecks.ToArray(), otherFailedChecks.ToArray());

newFailedChecks 和otherFailedChecks 都是List。当该方法作为 SOAP 服务在 IIS 上运行时,这一直运行良好。

但是,在我将完全相同的方法复制到 WCF 服务后,调用产生了“400 错误请求”异常。

最终我发现 .ToArray() 确实是问题所在。这:

Webclient.CheckGfiHelpdesks(Ticket, newFailedChecks.ToArray<GfiCheck>(), otherFailedChecks.ToArray<GfiCheck>());

即使用 System.Linq.Enumerable.ToArray<T>()而不是 System.Collections.Generic.List<T>.ToArray()终于解决了问题,异常消失了。

这种差异的解释是什么?数组是数组,但显然不是?

确切的异常(exception)是:

System.ServiceModel.ProtocolException

The remote server returned an unexpected response: (400) Bad Request.

堆栈跟踪:

Server stack trace:

at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException, ChannelBinding channelBinding)

at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)

at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)

at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)

at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)

at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

>

Exception rethrown at [0]:

at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)

at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

at MonitoringService.BL.CentronService.ICentronService.CheckGfiHelpdesks(String ticket, GfiCheck[] newHelpdeskChecks, GfiCheck[] otherChecks)

at MonitoringService.BL.CentronService.CentronServiceClient.CheckGfiHelpdesks(String ticket, GfiCheck[] newHelpdeskChecks, GfiCheck[] otherChecks) in C:\Users\sohrm\documents\visual studio 2010\Projects\MonitoringService\MonitoringService.BL\Service References\CentronService\Reference.cs:Zeile 5368.

at MonitoringService.BL.ConnectorBL.CheckHelpdesks(List`1 clients) in C:\Users\sohrm\documents\visual studio 2010\Projects\MonitoringService\MonitoringService.BL\ConnectorBL.cs:Zeile 120.

at MonitoringService.WinForm.MainForm.LoadChecks() in C:\Users\sohrm\documents\visual studio 2010\Projects\MonitoringService\MonitoringService.Client\MainForm.cs:Zeile 124.

at MonitoringService.WinForm.MainForm.btnLoad_Click(Object sender, EventArgs e) in C:\Users\sohrm\documents\visual studio 2010\Projects\MonitoringService\MonitoringService.Client\MainForm.cs:Zeile 114.

at System.Windows.Forms.Control.OnClick(EventArgs e)

at DevExpress.XtraEditors.BaseButton.OnClick(EventArgs e)

at DevExpress.XtraEditors.BaseButton.OnMouseUp(MouseEventArgs e)

at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)

at System.Windows.Forms.Control.WndProc(Message& m)

at DevExpress.Utils.Controls.ControlBase.WndProc(Message& m)

at DevExpress.XtraEditors.BaseControl.WndProc(Message& msg)

at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)

at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)

at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)

at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)

at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.Run(Form mainForm)

at MonitoringService.WinForm.Program.Main() in C:\Users\sohrm\documents\visual studio 2010\Projects\MonitoringService\MonitoringService.Client\Program.cs:Zeile 22.

at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)

at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading.ThreadHelper.ThreadStart()

最佳答案

System.Collections.Generic.List<T>.ToArray() 之间应该没有区别和 System.Linq.Enumerable.ToArray<T>() .让我们看看里面发生了什么:

System.Collections.Generic.List<T> 只是创建新数组并将内部项目数组复制到它:

public T[] ToArray()
{
T[] destinationArray = new T[this._size];
Array.Copy(this._items, 0, destinationArray, 0, this._size);
return destinationArray;
}

System.Linq.Enumerable 无法访问列表的内部项目数组,因此它通过缓冲区创建数组:

public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull("source");

Buffer<TSource> buffer = new Buffer<TSource>(source);
return buffer.ToArray();
}

缓冲区内发生了什么? List<T>ICollection<T>因此它只是调用CopyTo实现List<T> :

internal Buffer(IEnumerable<TElement> source)
{
TElement[] array = null;
ICollection<TElement> is2 = source as ICollection<TElement>;
length = is2.Count;
if (length > 0)
{
array = new TElement[length];
// implemented as Array.Copy(this._items, 0, array, 0, this._size);
is2.CopyTo(array, 0);
}

this.items = array;
this.count = length;
}

如您所见,项目通过列表的 CopyTo 方法复制到新数组,这与 ToArray 方法中的操作完全相同。但是用System.Linq.Enumerable你有一个小缺点——列表项被复制到缓冲区后,另一个数组被创建,缓冲区中的项被复制到该数组:

internal TElement[] ToArray()
{
if (this.count == 0)
return new TElement[0];

if (this.items.Length == this.count)
return this.items;

TElement[] destinationArray = new TElement[this.count];
Array.Copy(this.items, 0, destinationArray, 0, this.count);
return destinationArray;
}

因此,在这两种情况下,列表中的项目都通过相同的方法复制到新数组 Array.Copy .但在 Enumerable 的情况下这发生了两次。我宁愿选择列表的 ToArray如果我处理 List 的实现.

关于c# - System.Collections.Generic.List<T>.ToArray() 和 System.Linq.Enumerable.ToArray<T>() 之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10494545/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com