首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么时候LINQ (to对象)被过度使用了?

什么时候LINQ (to对象)被过度使用了?
EN

Stack Overflow用户
提问于 2010-04-15 20:09:20
回答 2查看 844关注 0票数 8

我的职业生涯最初是一个硬核心功能范式开发人员(LISP),现在我是一个硬核心.net/C#开发人员。我当然很喜欢LINQ。然而,我也相信:(1)使用适合工作的工具;(2)保留KISS原则:在与我一起工作的60+工程师中,也许只有20%的人拥有LINQ /Functional范式经验,5%的工程师有6到12个月的经验。简而言之,我觉得必须远离LINQ,除非我在没有LINQ的情况下无法实现目标(其中用一行LINQ替换3行O-O代码并不是“目标”)。

但是现在有一位工程师,已经有了12个月的LINQ /Functional-范例经验,正在生产代码中的每一个可以想象的位置使用LINQ对象,或者至少是lambda表达式。我对接吻原则的各种呼吁都没有产生任何结果。所以..。

我接下来能呼吁哪些发表的研究?什么“编码标准”准则,其他人捏造了一些成功?有没有我能指出的已发表的LINQ性能问题?简而言之,我正试图通过间接说服来实现我的第一个目标--亲吻。

当然,这个问题可以扩展到无数其他领域(例如过度使用扩展方法)。也许有一个"uber“指南,受到高度重视(例如,发表的研究等),在这方面采取了更广泛的举措。什么都行?

后期编辑:哇!我被教育了!我同意我来这里是完全错误的。但作为澄清,请看下面我看到的示例代码。它最初是编译和工作的,但现在它的目的已经无关紧要了。跟着它的“感觉”走吧。半年后,我又重新审视了这个例子,现在我得到了一个完全不同的画面,究竟是什么困扰着我。但我想有比我的眼睛更好的评论。

代码语言:javascript
复制
//This looks like it was meant to become an extension method...
public class ExtensionOfThreadPool
{
    public static bool QueueUserWorkItem(Action callback)
    {
        return ThreadPool.QueueUserWorkItem((o) => callback());
    }
}

public class LoadBalancer
{
    //other methods and state variables have been stripped...

    void ThreadWorker()
    {
        // The following callbacks give us an easy way to control whether
        // we add additional headers around outbound WCF calls.
        Action<Action> WorkRunner = null;

        // This callback adds headers to each WCF call it scopes
        Action<Action> WorkRunnerAddHeaders = (Action action) =>
        {
            // Add the header to all outbound requests. 
            HttpRequestMessageProperty httpRequestMessage = new HttpRequestMessageProperty();
            httpRequestMessage.Headers.Add("user-agent", "Endpoint Service");

            // Open an operation scope - any WCF calls in this scope will add the
            // headers above.
            using (OperationContextScope scope = new OperationContextScope(_edsProxy.InnerChannel))
            {
                // Seed the agent id header
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestMessage;

                // Activate
                action();
            }
        };

        // This callback does not add any headers to each WCF call
        Action<Action> WorkRunnerNoHeaders = (Action action) =>
        {
            action();
        };

        // Assign the work runner we want based on the userWCFHeaders
        // flag.
        WorkRunner = _userWCFHeaders ? WorkRunnerAddHeaders : WorkRunnerNoHeaders;

        // This outter try/catch exists simply to dispose of the client connection
        try
        {
            Action Exercise = () =>
            {
                // This worker thread polls a work list
                Action Driver = null;
                Driver = () =>
                {
                    LoadRunnerModel currentModel = null;
                    try
                    {
                        // random starting value, it matters little
                        int minSleepPeriod = 10;
                        int sleepPeriod = minSleepPeriod;

                        // Loop infinitely or until stop signals
                        while (!_workerStopSig)
                        {
                            // Sleep the minimum period of time to service the next element
                            Thread.Sleep(sleepPeriod);

                            // Grab a safe copy of the element list
                            LoadRunnerModel[] elements = null;
                            _pointModelsLock.Read(() => elements = _endpoints);

                            DateTime now = DateTime.Now;
                            var pointsReadyToSend = elements.Where
                                (
                                    point => point.InterlockedRead(() => point.Live && (point.GoLive <= now))
                                ).ToArray();

                            // Get a list of all the points that are not ready to send
                            var pointsNotReadyToSend = elements.Except(pointsReadyToSend).ToArray();

                            // Walk each model - we touch each one inside a lock
                            // since there can be other threads operating on the model
                            // including timeouts and returning WCF calls.
                            pointsReadyToSend.ForEach
                            (
                                model =>
                                {
                                    model.Write
                                    (
                                        () =>
                                        {
                                            // Keep a record of the current model in case
                                            // it throws an exception while we're staging it
                                            currentModel = model;

                                            // Lower the live flag (if we crash calling
                                            // BeginXXX the catch code will re-start us)
                                            model.Live = false;

                                            // Get the step for this model
                                            ScenarioStep step = model.Scenario.Steps.Current;

                                            // This helper enables the scenario watchdog if a
                                            // scenario is just starting
                                            Action StartScenario = () =>
                                            {
                                                if (step.IsFirstStep && !model.Scenario.EnableWatchdog)
                                                {
                                                    model.ScenarioStarted = now;
                                                    model.Scenario.EnableWatchdog = true;
                                                }
                                            };

                                            // make a connection (if needed)
                                            if (step.UseHook && !model.HookAttached)
                                            {
                                                BeginReceiveEventWindow(model, step.HookMode == ScenarioStep.HookType.Polled);
                                                step.RecordHistory("LoadRunner: Staged Harpoon");
                                                StartScenario();
                                            }

                                            // Send/Receive (if needed)
                                            if (step.ReadyToSend)
                                            {
                                                BeginSendLoop(model);
                                                step.RecordHistory("LoadRunner: Staged SendLoop");
                                                StartScenario();
                                            }

                                        }
                                    );
                                }
                                , () => _workerStopSig
                            );

                            // Sleep until the next point goes active. Figure out
                            // the shortest sleep period we have - that's how long
                            // we'll sleep.
                            if (pointsNotReadyToSend.Count() > 0)
                            {
                                var smallest = pointsNotReadyToSend.Min(ping => ping.GoLive);
                                sleepPeriod = (smallest > now) ? (int)(smallest - now).TotalMilliseconds : minSleepPeriod;
                                sleepPeriod = sleepPeriod < 0 ? minSleepPeriod : sleepPeriod;
                            }
                            else
                                sleepPeriod = minSleepPeriod;
                        }
                    }
                    catch (Exception eWorker)
                    {
                        // Don't recover if we're shutting down anyway
                        if (_workerStopSig)
                            return;

                        Action RebootDriver = () =>
                        {
                            // Reset the point SendLoop that barfed
                            Stagepoint(true, currentModel);

                            // Re-boot this thread
                            ExtensionOfThreadPool.QueueUserWorkItem(Driver);
                        };

                        // This means SendLoop barfed
                        if (eWorker is BeginSendLoopException)
                        {
                            Interlocked.Increment(ref _beginHookErrors);
                            currentModel.Write(() => currentModel.HookAttached = false);
                            RebootDriver();
                        }
                        // This means BeginSendAndReceive barfed
                        else if (eWorker is BeginSendLoopException)
                        {
                            Interlocked.Increment(ref _beginSendLoopErrors);
                            RebootDriver();
                        }
                        // The only kind of exceptions we expect are the 
                        // BeginXXX type. If we made it here something else bad
                        // happened so allow the worker to die completely.
                        else
                            throw;
                    }
                };

                // Start the driver thread. This thread will poll the point list
                // and keep shoveling them out
                ExtensionOfThreadPool.QueueUserWorkItem(Driver);

                // Wait for the stop signal
                _workerStop.WaitOne();

            };

            // Start
            WorkRunner(Exercise);
        }
        catch(Exception ex){//not shown}
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-04-15 20:15:05

嗯,在我看来,你似乎是想让代码变得更复杂的人--因为你认为你的同事不适合真正简单的方法。在许多情况下,我发现LINQ对象使代码更简单-是的,这包括只将几行更改为一行:

代码语言:javascript
复制
int count = 0;
foreach (Foo f in GenerateFoos())
{
    count++;
}

成为

代码语言:javascript
复制
int count = GenerateFoos().Count();

例如。

在没有使代码变得更简单的地方,尝试引导他远离LINQ是很好的--但上面的例子表明,避免LINQ显然不会对您造成明显的阻碍,但是"KISS“代码显然是LINQ代码。

听起来,你的公司可以通过培训工程师来利用LINQ,而不是总是试图吸引最低的公分母。

票数 16
EN

Stack Overflow用户

发布于 2010-04-15 20:14:55

您似乎将Linq等同于具有更大复杂性的对象,因为您认为不必要的使用它违反了“保持简单,愚蠢”。

我所有的经验都恰恰相反:它使复杂的算法更易于编写和读取。

相反,我现在认为必须的、基于语句的、状态突变的编程是“有风险的”选择,只有在真正需要的时候才能使用。

因此,我建议你努力让更多的同事了解这种好处。试图将您的方法局限于您(和其他人)已经理解的方法是一种错误的经济,因为在这个行业中,与“新”实践保持联系会带来巨大的好处(当然,这不是什么新的东西,但正如您所指出的,这对许多来自Java或C# 1.x背景的人来说是新的)。

至于试图将“性能问题”归咎于此,我不认为你会有多大的运气。Linq到对象本身所涉及的开销是很小的。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2648626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档