Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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# 如何重写bool TrySomething(列出<;T>;项,列出<;T>;项失败)_C#_Design Patterns_Coding Style_Out - Fatal编程技术网

C# 如何重写bool TrySomething(列出<;T>;项,列出<;T>;项失败)

C# 如何重写bool TrySomething(列出<;T>;项,列出<;T>;项失败),c#,design-patterns,coding-style,out,C#,Design Patterns,Coding Style,Out,我有这个功能: bool TrySomething(IEnumerable<T> items, out List<T> listOfProblemItems) { //... return listOfProblemItems != null && listOfProblemItems.Count > 0; } 如果出现问题,返回true是不直观的,但是如果我将其更改为false,那么out参数将填充false的信息,从而打破“T

我有这个功能:

bool TrySomething(IEnumerable<T> items, out List<T> listOfProblemItems)
{
    //...

    return listOfProblemItems != null && listOfProblemItems.Count > 0;
}
如果出现问题,返回
true
是不直观的,但是如果我将其更改为
false
,那么
out
参数将填充
false
的信息,从而打破“TrySomething”模式

对我来说,抛出异常不是一种选择,因为这是一个高性能的项目,我需要一个明确定义的列表,列出哪些项目失败了

我可以让它返回问题列表并将其命名为
trysomethin和returnanyproblems
,但这个名称很难看,调用代码必须检查返回的列表中的null和计数,我宁愿在函数中这样做,因为无论如何都必须这样做

List<T> problems = TrySomethingAndReturnAnyProblems(items);
if(problems != null && problems.Count > 0)
{
    //ugly and introduces duplicate code every time the function is used.
}
List problems=trysomethin和returnanyproblems(项目);
if(problems!=null&&problems.Count>0)
{
//丑陋,每次使用该函数时都会引入重复代码。
}

如何在保持“TrySomething”模式的简洁性的同时,将其变成可读的、自文档化的函数定义?

编写一个扩展方法来简单地过滤出有问题的项怎么样?这样,您只能取回正常的项目,例如:

public static IEnumerable<T> ExceptProblematic(this IEnumerable<T> items)
{
  foreach (var item in items)
  {
    if (!IsProblematic(item))
      yield return item;
  }
}
或者,您可以编写一个查询以仅返回问题项,然后进行另一个查询以筛选出它们,例如:

var problemItems = items.Where(item => IsProblematic(item));
var validItems = items.Except(problemItems);
然后相应地处理问题项:

if (problemItems.Any()) 
{
   // handle problem items
}

bool Success
T Data
属性创建一个
Result
类怎么样

class Result<T>
{
     public bool Success {get; set;}
     public T Data {get; set;}
}

如果您担心破坏
TryX
模式,为什么不编一个:

public bool AntiTrySomething(IEnumerable<T> input, out IEnumerable<T> fails)
{
    // implement me - return true if fail
}
public bool AntiTrySomething(IEnumerable输入,out IEnumerable失败)
{
//实现me-如果失败则返回true
}

只要你在整个代码库中保持一致,我认为这样的东西是清楚的,它将你从“标准”中分离出来,在保持熟悉的同时不与之冲突。

我宁愿为结果创建一个特殊的类(参见Ahmed KRAIEM的回答) 但我会用一些不同的(精心设计的)方式:

公共密封类SomeResultWithDescription:IReadOnlyList{
私有列表m_问题;
私有布尔m_Success=true;//0)
返回false;
返回true;
}
}
公共布尔ToBoolean(){
回归成功;
}
公共静态隐式运算符布尔值(SomeResultWithDescription值){
if(Object.ReferenceEquals(null,value))
返回false;
返回值。ToBoolean();
}
公共滴度此[整数索引]{
得到{
返回m_问题[索引];
}
}
公共整数计数{
得到{
返回m_.Count;
}
}
公共IEnumerator GetEnumerator(){
返回m_问题。GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator(){
返回m_问题。GetEnumerator();
}
}
...
//你的方法是
SomeResultWithDescription尝试测量(IEnumerable items)
{
//...
返回新的SomeResultWithDescription(问题项列表);
}
//所以你可以
// 1. 如果没有检测到问题,请执行此操作
如果(尝试(项目)){
...
}
// 2. 如果没有问题就做,如果有问题就分析
var结果=试验测量(项目);
如果(结果){
…//没问题
}

其他的{//code>return listOfProblemItems==null | | listOfProblemItems.Count==0;
?顺便说一句,我会删除
bool
返回值并直接返回列表。调用方只需检查空列表……也许您不应该使用
TryX
模式。
TryX
方法使用
out
参数作为结果,not用于报告问题。您正在不时地打破这种模式。首先,自定义异常类型当然可以包含一系列问题。其次,如果没有抛出异常,则异常不会很慢。换句话说,当您的程序无法工作时,它真的必须不能很快工作吗?最后但并非最不重要的是,异常可能不会很快发生就像你想象的那样慢。你正在建立一个问题列表,然后在这个列表上循环。这个过程中的异常成本很可能是可以忽略的。@KrisVandermotten:他正在编写一个经常失败的方法,否则这个方法本身将是多余的。
int TrySomething怎么样(IEnumerable items,Action problemCallback)
?我不确定除了尝试运行操作并查看之外,
IsProblematic(item)
会做什么。在这种情况下,我可以创建一个
bool TrySomething(T item)
,我不能这么做,因为它是一个高性能函数,只有在传递大量项时才有用。
if (problemItems.Any()) 
{
   // handle problem items
}
class Result<T>
{
     public bool Success {get; set;}
     public T Data {get; set;}
}
Result<List<T>> result = TrySomething(enumerable);
if (!result.Success)
{
    List<T> problematicItems = result.Data;
    //...
}
public bool AntiTrySomething(IEnumerable<T> input, out IEnumerable<T> fails)
{
    // implement me - return true if fail
}
  public sealed class SomeResultWithDescription<TItem>: IReadOnlyList<TItem> {
    private List<TItem> m_Problems;
    private Boolean m_Success = true; // <- the field may be redundant 

    // may be redundant: if there's no situation when the result is falure
    // even if there're no problems enlisted
    internal SomeResultWithDescription(List<TItem> problems, Boolean success)
      : this(problems) {

      m_Success = success;
    }

    internal SomeResultWithDescription(List<TItem> problems)
      : base() {

      if (Object.ReferenceEquals(null, problems))
        m_Problems = new List<TItem>();
      else
        m_Problems = problems;
    }

    public IReadOnlyList<TItem> Problems {
      get {
        return m_Problems;
      }
    }

    public Boolean Success {
      get {
        if (!m_Success)
          return false;
        else if (m_Problems.Count > 0)
          return false;

        return true;
      }
    }

    public Boolean ToBoolean() {
      return Success;
    }

    public static implicit operator Boolean(SomeResultWithDescription<TItem> value) {
      if (Object.ReferenceEquals(null, value))
        return false;

      return value.ToBoolean();
    }

    public TItem this[int index] {
      get {
        return m_Problems[index];
      }
    }

    public int Count {
      get {
        return m_Problems.Count;
      }
    }

    public IEnumerator<TItem> GetEnumerator() {
      return m_Problems.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
      return m_Problems.GetEnumerator();
    }
  }

  ...

  // Your method will be
  SomeResultWithDescription<T> TrySomething(IEnumerable<T> items)
  {
    //...

    return new SomeResultWithDescription<T>(listOfProblemItems);
  }

  // So you can do
  // 1. Just do if no problems detected
  if (TrySomething(items)) { 
    ...
  }

  // 2. Do if no problems, analyze if there're problems
  var result = TrySomething(items);

  if (result) { 
    ... // no problems
  }
  else { // <- some problems to analyze
    foreach (var problem in result) {
      ...
    }
  }