C# 如何使switch语句更有效
我有一个用于多种枚举类型的switch语句,并根据该类型检查与该类型对应的时间戳是否在提供的日期范围内。我使用了10个开关,想知道是否有一个查询函数更高效 是否可以使用selectmany或where from linq来提高性能C# 如何使switch语句更有效,c#,performance,linq,C#,Performance,Linq,我有一个用于多种枚举类型的switch语句,并根据该类型检查与该类型对应的时间戳是否在提供的日期范围内。我使用了10个开关,想知道是否有一个查询函数更高效 是否可以使用selectmany或where from linq来提高性能 private Event[] FilterNotifications(Event[] eventResponseItems, DateTime beginDate, DateTime endDate) { var eventList = eventRespo
private Event[] FilterNotifications(Event[] eventResponseItems, DateTime beginDate, DateTime endDate)
{
var eventList = eventResponseItems.ToList();
foreach (var eEvent in eventList)
{
switch (eEvent.EventType)
{
case "RouteStarted":
if (!InRange(beginDate, endDate, eEvent.EventInfo.RouteInfo.RouteTimestamps.Started))
eventList.Remove(eEvent);
break;
case "RouteDeparted":
if (!InRange(beginDate, endDate, eEvent.EventInfo.RouteInfo.RouteTimestamps.Arrived))
eventList.Remove(eEvent);
break;
case "RouteArrived":
if (!InRange(beginDate, endDate, eEvent.EventInfo.RouteInfo.RouteTimestamps.Completed))
eventList.Remove(eEvent);
break;
case "RouteCompleted":
if (!InRange(beginDate, endDate, eEvent.EventInfo.RouteInfo.RouteTimestamps.Departed))
eventList.Remove(eEvent);
break;
case "StopArrived":
if (!InRange(beginDate, endDate, eEvent.EventInfo.StopInfo.ArrivalTimeStamp))
eventList.Remove(eEvent);
break;
case "StopDeparted":
if (!InRange(beginDate, endDate, eEvent.EventInfo.StopInfo.DepartureTimeStamp))
eventList.Remove(eEvent);
break;
case "StopServicing":
if (!InRange(beginDate, endDate, eEvent.EventInfo.StopInfo.ArrivalTimeStamp))
eventList.Remove(eEvent);
break;
case "StopCancelled":
if (!InRange(beginDate, endDate, eEvent.EventInfo.StopInfo.DepartureTimeStamp))
eventList.Remove(eEvent);
break;
case "RouteStatusChanged":
if (!InRange(beginDate, endDate, eEvent.EventInfo.StopInfo.ArrivalTimeStamp))
eventList.Remove(eEvent);
break;
}
}
return eventList.ToArray();
}
private bool InRange(DateTime beginTime, DateTime endTime, string timeStamp)
{
DateTime timeStmp = DateConverter.ToInternal(timeStamp).Value;
if ( timeStmp >= beginTime)
{
if (endTime != new DateTime() && timeStmp <= endTime)
{
return true;
}
return true;
}
return false;
}
私有事件[]过滤器通知(事件[]事件响应项、日期时间开始日期、日期时间结束日期)
{
var eventList=eventResponseItems.ToList();
foreach(事件列表中的变量eEvent)
{
开关(eEvent.EventType)
{
案例“RouteStarted”:
if(!InRange(beginDate、endDate、eEvent.EventInfo.RouteInfo.RouteTimestamps.Started))
事件列表。删除(eEvent);
打破
案例“RoutedParted”:
if(!InRange(beginDate、endDate、eEvent.EventInfo.RouteInfo.RouteTimestamps.Arrived))
事件列表。删除(eEvent);
打破
案例“RouteArrived”:
如果(!InRange(beginDate、endDate、eEvent.EventInfo.RouteInfo.RouteTimestamps.Completed))
事件列表。删除(eEvent);
打破
案例“RouteCompleted”:
如果(!InRange(beginDate、endDate、eEvent.EventInfo.RouteInfo.RouteTimestamps.deceed))
事件列表。删除(eEvent);
打破
案例“停止到达”:
如果(!InRange(beginDate、endDate、eEvent.EventInfo.StopInfo.ArrivalTimeStamp))
事件列表。删除(eEvent);
打破
“停止”一案:
if(!InRange(beginDate、endDate、eEvent.EventInfo.StopInfo.DepartureTimeStamp))
事件列表。删除(eEvent);
打破
案例“停止服务”:
如果(!InRange(beginDate、endDate、eEvent.EventInfo.StopInfo.ArrivalTimeStamp))
事件列表。删除(eEvent);
打破
案例“停止取消”:
if(!InRange(beginDate、endDate、eEvent.EventInfo.StopInfo.DepartureTimeStamp))
事件列表。删除(eEvent);
打破
案例“RouteStatusChanged”:
如果(!InRange(beginDate、endDate、eEvent.EventInfo.StopInfo.ArrivalTimeStamp))
事件列表。删除(eEvent);
打破
}
}
返回eventList.ToArray();
}
范围内的私有布尔值(日期时间开始时间、日期时间结束时间、字符串时间戳)
{
DateTime timeStmp=DateConverter.ToInternal(timeStamp).Value;
如果(timeStmp>=beginTime)
{
如果(endTime!=new DateTime()&&timeStmp在您的方法中没有太多的性能优化,因为它不使用任何复杂的迭代
从可读性的角度来看,您可以使用字典。这还可以避免使用.Where()
完全具体化返回的数组
要将每个事件的事件信息枚举转换为时间戳字符串,需要一个稍微复杂的Func
,如下所示
var RouteControl = new Dictionary<string,Func<Event,string>>()
{
{ "RouteStarted" , eEvent => eEvent.EventInfo.RouteInfo.RouteTimestamps.Started },
{ "RouteDeparted" , eEvent => eEvent.EventInfo.RouteInfo.RouteTimestamps.Arrived },
{ "RouteArrived" , eEvent => eEvent.EventInfo.RouteInfo.RouteTimestamps.Completed },
{ "RouteCompleted" , eEvent => eEvent.EventInfo.RouteInfo.RouteTimestamps.Departed },
{ "StopArrived" , eEvent => eEvent.EventInfo.StopInfo.ArrivalTimeStamp },
{ "StopDeparted" , eEvent => eEvent.EventInfo.StopInfo.DepartureTimeStamp },
{ "StopServicing" , eEvent => eEvent.EventInfo.StopInfo.ArrivalTimeStamp },
{ "StopCancelled" , eEvent => eEvent.EventInfo.StopInfo.DepartureTimeStamp },
{ "RouteStatusChanged" , eEvent => eEvent.EventInfo.StopInfo.ArrivalTimeStamp }
};
return eventResponseItems.Where(eEvent =>
!RouteControl.ContainsKey(eEvent.EventType) ||
InRange(beginDate, endDate, RouteControl[eEvent.EventType](eEvent))
).ToArray();
var RouteControl=new Dictionary()
{
{“RouteStarted”,eEvent=>eEvent.EventInfo.RouteInfo.RouteTimestamps.Started},
{“RoutedParted”,eEvent=>eEvent.EventInfo.RouteInfo.RouteTimestamps.Arrized},
{“RouteArrived”,eEvent=>eEvent.EventInfo.RouteInfo.RouteTimestamps.Completed},
{“RouteCompleted”,eEvent=>eEvent.EventInfo.RouteInfo.RouteTimestamps.Deceed},
{“stopArrival”,eEvent=>eEvent.EventInfo.StopInfo.ArrivalTimeStamp},
{“stoppendered”,eEvent=>eEvent.EventInfo.StopInfo.DepartureTimeStamp},
{“停止服务”,eEvent=>eEvent.EventInfo.StopInfo.ArrivalTimeStamp},
{“StopCancelled”,eEvent=>eEvent.EventInfo.StopInfo.DepartureTimeStamp},
{“RouteStatusChanged”,eEvent=>eEvent.EventInfo.StopInfo.ArrivalTimeStamp}
};
return eventResponseItems.Where(eEvent=>
!RouteControl.ContainsKey(eEvent.EventType)||
InRange(beginDate、endDate、RouteControl[eEvent.EventType](eEvent))
).ToArray();
List.Remove在O(n)中,所以整个循环在O(n^2)中。如果在只包含所需元素的第一个列表上迭代时填充第二个列表,则可能会提高性能。我更关心的是代码的可维护性,而不是性能。如果我们从尝试删除重复代码开始,并使剩余的代码易于理解,我最终会使用som就像这样:
private Event[] FilterNotifications(Event[] eventResponseItems, DateTime beginDate, DateTime endDate)
{
return eventResponseItems
.Where(e => InRange(beginDate, endDate, GetEventRouteTimeStampFromEventType(e.EventInfo.RouteInfo.RouteTimestamps, e.EventType)))
.ToArray();
}
private string GetEventRouteTimeStampFromEventType(RouteTimeStamps routeTimeStamps, string eventType)
{
switch (eventType)
{
case "RouteStarted":
case "StopCancelled":
return routeTimestamps.Started;
case "RouteDeparted":
return routeTimestamps.Arrived;
case "RouteArrived":
return routeTimestamps.Completed;
case "RouteCompleted":
return routeTimestamps.Departed;
case "StopDeparted":
return routeTimestamps.DepartureTimeStamp;
case "RouteStatusChanged":
case "StopServicing":
case "StopArrived":
return routeTimestamps.ArrivalTimeStamp;
default: throw new ArgumentOutOfRangeException();
}
}
}
而且,事实上,这也恰好获得了更好的性能(因为您在进行筛选,而不是创建列表并从中删除项目)。因此,这是一个很好的胜利
请注意,我假定您有一个有限的事件类型列表,如果您看到任何其他事件,您希望抛出一个异常(这通常是在选择switch语句时的情况)。如果不是这样,您可以执行类似于返回null的操作,并相应地调整剩余代码。在不知道您在这里执行的操作的情况下,我观察到您似乎正在查询范围分隔符不变的循环内的日期范围。在考虑之前,您可以在循环外创建一个子范围g事件类型,仅查询循环中的子范围?代码是否存在性能问题?我只是好奇这是否是过早优化的情况。因为第一个if
条件中的所有代码路径都返回true
(在InRange
方法中),不需要嵌套的if
语句(或者第二个return true;
应该是return false;
)代码看起来很好,我看不出Linq
方法如何提高性能。在释放模式下的开关