Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/10.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# 我想用更优雅的结构_C# - Fatal编程技术网

C# 我想用更优雅的结构

C# 我想用更优雅的结构,c#,C#,我不是C的高级,所以我可能应该学习更多的基础知识,但下面是我的代码: var out1 = obj1.F1(); var out2 = obj2.F2(out1); var out3 = obj3.F3(out2); var out4 = obj4.F4(out3); 另一种方法是在一行中执行相同的操作: var out4 = obj4.F4( obj3.F3( obj2.F2( obj1.F1() ) ) ); 但是xml标记很难读取,而且层次性更高 所以我想让它更实用。它应该看起来像“

我不是C的高级,所以我可能应该学习更多的基础知识,但下面是我的代码:

var out1 = obj1.F1();
var out2 = obj2.F2(out1);
var out3 = obj3.F3(out2);
var out4 = obj4.F4(out3);
另一种方法是在一行中执行相同的操作:

var out4 = obj4.F4( obj3.F3( obj2.F2( obj1.F1()  ) ) );
但是xml标记很难读取,而且层次性更高

所以我想让它更实用。它应该看起来像“管道”、“输送机”,其中一个功能的输出是另一个功能的输入。我的拐杖解决方案:

var obj = new[]{0}; //first looking bad thing, without that you are operating with each element of F1() result
var something = obj
       .Select(x => obj1.F1() ) //second: x=>  x doesn't take part in right side
       .Select(x => obj2.F2(x) )
       .Select(x => obj3.F3(x) )
       .Select(x => obj4.F4(x) )
       .ToArray(); //third: without that it doesn't do anything
您应该如何编写此“模式”?

而不是尝试使用Enumerable。Select是为序列设计的,而不是您拥有的序列。您只需创建一个运算符,对单个项目执行相同的操作即可:

public static TResult Map<TSource, TResult>(
    this TSource source, Func<TSource, TResult> selector)
{
    return selector(source);
}

好吧,你的例子有点糟糕,因为我不知道这些方法到底在做什么。他们的名字没有任何可以推断其目的的东西,因此我们无法就如何继续向您提供太多建议

例如,假设这是一个图像处理库,您正在执行以下操作:

这是伪代码

var img = new Image();
var trimmedImage = TrimWhitespace(img);
var rotatedImage = RotateImage(trimmedImage);
var zoomedImage = ZoomImage(rotatedImage);
我仍然不会链接它们,但如果我需要以表示层格式重用它,我会设置一个对象来协调它,即:

var formattedImage = ImageFormatter.Format(new Image());

ImageFormatter将按照psuedocode中列出的顺序调用它们。

您可以执行以下操作:

var result = obj1.F1().Pipe(obj2.F2).Pipe(obj3.F3).Pipe(obj4.F4);
使用以下扩展方法

static class Extensions
{
    public static TOut Pipe<TIn, TOut>(this TIn input, Func<TIn, TOut> func)
    {
        return func(input);
    }
}


不确定它是否真的更具可读性,不过…

去看看。需要更多细节。您使用obj1.F1的目的是什么??有可能是用另一种方法来实现的。这听起来像是违反了德米特定律。读了一段时间后,我认为问题可能仅仅在于什么对象拥有这些方法。我会尝试将方法从obj1的类型移动到out1的类型。这样的问题更适合。看起来不错。我知道调试更困难,但也更表达可能有点荒谬,但我还创建了返回新对象的静态方法BeginPipe,所以用法是:var result=BeginPipe.Pipe x=>obj.F1.Pipe x=>obj2.F2x….@JamesBrolin为什么?它给了你什么?你为什么不像我在这里做的那样?“有点荒谬”我是说我的版本。很抱歉输入一条注释而不是新行您的解决方案完全适合。这只是我的想法,如何让它更实用和统一,好吗?很高兴看到你使用MethodGroup。除此之外,它与Servy的答案相同。您的扩展与Servy的扩展相同,但他的示例看起来更简单readable@JamesBrolin,嗯,我觉得我的书更可读,但我想这是个人喜好的问题@Thomasleveque:我认为很多人不熟悉方法组语法。我很少看到它,即使它显然是适用的。你可能会提出一些“现在你不知道它是接受委托还是接受变量”的论点,但我不这么认为。一旦你花时间学习它,它就相当简单了。@JamesBrolin,把它想象成shell命令:obj1.F1 | obj2.F2 | obj3.F3 | obj4.f4如果可能的话,我会在图像中包含TrimWhitespace、Rotate和Zoom方法,并让它们返回新图像。这将允许链接或这种语法,尽管您的代码与问题的不同之处在于有四个实例正在操作。我想如果您愿意,您可以将它们作为扩展方法写入映像,但我倾向于避免使用扩展方法,因为它们不太清楚。也许,但我认为你把自己的建议和现实搞混了。这些是任意类,大概是他控制的类。在这种情况下,不需要使用扩展方法。我想是你把它弄糊涂了。OP没有向我们提供有关obj1.F1输出的任何详细信息。这可能是一条你所知道的线。你对他的实现做了一个疯狂的假设。他在问一个不确定的模式,对不确定的对象做不确定的事情。我认为最安全的假设是他正在变异一个CLR类。
static class Extensions
{
    public static TOut Pipe<TIn, TOut>(this TIn input, Func<TIn, TOut> func)
    {
        return func(input);
    }
}