【问题标题】:C# best way to create instance level interface [closed]C# 创建实例级接口的最佳方法 [关闭]
【发布时间】:2021-02-03 07:02:39
【问题描述】:

例如,假设我有一个带有一堆节点的有向无环图。我想遍历图,但是每个节点都有一个保护条件。例如,如果节点A的值小于10,我只能遍历到节点B。所以我创建了一个名为IsActive的方法,它是特定于每个节点的。我尝试使用抽象类方法对此进行建模:

abstract class Node
{
    public int value;
    public abstract bool IsActive();
}

class NodeB : Node
{
    public override bool IsActive()
    {
        // return nodeA.value < 10
    }
}

但是,我想避免为每个节点创建一个新类。那么在实例级别初始化/实现方法的最佳方法是什么?我做了一些其他的事情,但我真的不确定“最好”的方法是什么......

谢谢!

【问题讨论】:

  • 您对“最佳方式”的标准是什么?
  • 保护子句是如何定义的?它取决于价值,还是可以是任何条款?例如仅在星期一?也许您可以使用委托来确定节点是否处于活动状态并仅注入“Action”?
  • 我猜,什么会被认为是最佳实践。使用在实例级别初始化/实现的方法来定义类的常规方法是什么?
  • 它可以是任何条件,所以它可能是 A > 10 && C C 等
  • 在基类中为IsActive 提供默认实现并使其成为虚拟?还是将IsActive 设为可以设置的属性?或者您所说的“避免为每个节点创建一个新类”是什么意思?您想要每个节点的类的实例,不是吗?

标签: c# oop interface abstract-class


【解决方案1】:

您可以在 Node 类中拥有一个 Func&lt;bool&gt; 作为属性:

public class Node
{
 public int Value {get;set;}
 public Func<bool> IsActiveFunction { get; set; }
 public bool IsActive()
 {
   return IsActiveFunction.Invoke();
 }
}

这样你就可以独立定义每个节点的条件:

Node nodeA = new Node();
Node nodeB = new Node();
nodeA.IsActiveFunction = () => nodeB.Value < 10;
nodeB.IsActiveFunction = () => Math.sin(nodeA.Value) == 0; // bad example, because you should not use == to compare doubles, but you get the idea

【讨论】:

    【解决方案2】:

    你不需要很多课。您可以简单地使用您的 Node 类,但对其进行修改。

    public class Node
    {
        public int Value { get; set; } = 0;
        public int LowerValueLimit { get; set; } = int.MinValue;
        public int UpperValueLimit { get; set; } = int.MaxValue;
        public bool IsActive()
        {
            return Value >= LowerValueLimit  && Value <= UpperValueLimit ;
        }
    }
    

    现在只需使用其内置逻辑创建您的节点

    // is active will be true for anything between int.MinValue to 10
    var nodeA = new Node() { UpperValueLimit = 10 }; 
    
     // will be active for value between 50 and 60
    var nodeB = new Node()  { LowerValueLimit = 50, UpperValueLimit = 60 };
    

    【讨论】:

      【解决方案3】:

      我会更进一步,创建可用于创建验证逻辑的接口

      using System;
      using System.Collections.Generic;
      using System.Linq;
      
      namespace NodeExample
      {
          class Program
          {
              static void Main(string[] args)
              {
                  var graphRoot = new Node(1);
      
                  var nodeA = new Node(7, new ValidateNodeBehaviour(currentNode => currentNode.Value >= 5));
                  var nodeB = new Node(3, new ValidateNodeBehaviour(currentNode => currentNode.Value >= 10 && nodeA.Value <= 10));
                  var nodeC = new Node(4);
      
                  graphRoot.Connections.Add(nodeA);
                  graphRoot.Connections.Add(nodeB);
      
                  nodeB.Connections.Add(nodeC);
      
                  //traverse the graph
                  var currentNode = graphRoot;
                  while (true)
                  {
                      var availableConnection = currentNode.Connections.FirstOrDefault(x => x.IsValid());
      
                      if (availableConnection == null)
                          break;
      
                      currentNode = availableConnection;
                  }
              }
          }
      
          public interface IValidatableBehavior
          {
              public bool IsValid(Node currentNode);
          }
      
          public class ValidateNodeBehaviour : IValidatableBehavior
          {
              private Func<Node, bool> validateFunc;
              public ValidateNodeBehaviour(Func<Node, bool> validateFunc)
              {
                  this.validateFunc = validateFunc ?? throw new ArgumentNullException(nameof(validateFunc));
              }
      
              public bool IsValid(Node currentNode)
              {
                  return validateFunc(currentNode);
              }
          }
      
          public class Node
          {
              private readonly IValidatableBehavior validatableBehavior;
      
              public int Value { get; set; }
              public List<Node> Connections { get; } = new List<Node>();
      
      
              public Node(int value)
              {
                  Value = value;
              }
      
              public Node(int value, IValidatableBehavior validatableBehavior) : this(value)
              {
                  this.validatableBehavior = validatableBehavior;
              }
      
              public bool IsValid()
              {
                  if (validatableBehavior == null)
                  {
                      return true;
                  }
      
                  return validatableBehavior.IsValid(this);
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-24
        • 2013-02-16
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 2013-02-17
        相关资源
        最近更新 更多