Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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# 如何使switch语句更有效_C#_Performance_Linq - Fatal编程技术网

C# 如何使switch语句更有效

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

我有一个用于多种枚举类型的switch语句,并根据该类型检查与该类型对应的时间戳是否在提供的日期范围内。我使用了10个开关,想知道是否有一个查询函数更高效

是否可以使用selectmany或where from linq来提高性能

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
方法如何提高性能。在释放模式下的
开关