【问题标题】:C# how to make a function that can return either child or parent classC#如何创建一个可以返回子类或父类的函数
【发布时间】:2014-12-19 13:07:24
【问题描述】:

不确定我是否在标题上说清楚了。我想要的是这个:
有一个父类:

public class parent  
....  

还有一个子类:

public class child : parent  
....  

现在我需要一个可以返回的方法:

List<(what goes here?)> GetSomeValue(string id, boolean needChild) {  
  ......  
  if (needChild)  
    return BuildChildResult(id);  
  else  
    return BuildParentResult(id);  
}  

这有可能吗?
括号里应该是什么?

【问题讨论】:

  • 为什么加4个空格不能识别代码块??
  • 返回 List 怎么样?但是当你遍历列表时你必须检查类型......
  • 尝试使用T的泛型函数
  • list GetSomeValue(string id) where T : parent { ... }
  • @AllenZhang 尝试阅读我的答案

标签: c#


【解决方案1】:

返回不同类型的 List&lt;T&gt; 将不起作用,因为 List 不是 Covariant

您可以通过降低对实现out 通用修饰符(即IEnumerable&lt;T&gt;)的接口级别的响应来实现您的目标

所以在这个示例代码模型中,它应该可以工作。

private static IEnumerable<Parent> Test(bool flag) // returns a covariant collection
{
    if (flag)
        return new List<Parent>(); 
    else
        return new List<Child>();
} 

阅读更多关于Covariance and Contravariance

【讨论】:

    【解决方案2】:

    您可以为类添加一个接口,并让您的方法返回一个接口而不是具体类型。

    但是我要指出,由于这是一个孩子或父母,没有其他逻辑,我会考虑使用两种方法来避免强制转换。看起来它可以节省代码以将其包装在单个方法中,但请记住,转换/分支的复杂性随后会被推送给调用者。

    【讨论】:

    • 如果进一步处理需要这些属性,这是否会导致丢失子特定属性?
    • @shree.pat18 特定于子的属性确实需要进一步处理。
    • 添加一个属性来区分接口上的类型并根据需要进行强制转换。
    • 如果用于处理的方法名称相同,您可以从这里的多态性中受益
    • @TCG 在返回值中只使用父类型是否有害?
    【解决方案3】:

    我认为界面是要走的路。看看这个程序:

    class Program
    {
        static void Main(string[] args)  
        {
            bool needChild = true;
    
            IEnumerable<IMyClass> myChildList = GetSomeValue("1", needChild);
            List<Child> myChildren = myChildList.Cast<Child>().ToList();
    
            needChild = false;
            IEnumerable<IMyClass> myParentList = GetSomeValue("1", needChild);
            List<Parent> myParents = myParentList.Cast<Parent>().ToList();
    
        }
    
        private static IEnumerable<IMyClass> GetSomeValue(string id, bool needChild)
        {
            if (needChild)
            {
                return BuildChildResult(id);
            }
    
            return BuildParentResult(id);
        }
    
        private static IEnumerable<IMyClass> BuildChildResult(string id)
        {
            var list = new List<IMyClass>
            {
                new Child {ChildName = "Test 1", Id = "1"},
                new Child {ChildName = "Test 2", Id = "1"},
                new Child {ChildName = "Test 3", Id = "1"},
                new Child {ChildName = "Test 4", Id = "2"},
                new Child {ChildName = "Test 4", Id = "2"},
                new Child {ChildName = "Test 4", Id = "3"}
            };
    
            return list.Where(z => z.Id == id).ToList();
        }
    
        private static IEnumerable<IMyClass> BuildParentResult(string id)
        {
            var list = new List<IMyClass>
            {
                new Parent {ParentName = "Test 1", Id = "1"},
                new Parent {ParentName = "Test 2", Id = "1"},
                new Parent {ParentName = "Test 3", Id = "1"},
                new Parent {ParentName = "Test 4", Id = "2"},
                new Parent {ParentName = "Test 4", Id = "2"},
                new Parent {ParentName = "Test 4", Id = "3"}
            };
    
            return list.Where(z => z.Id == id).ToList();
        }
    }
    
    public interface IMyClass
    {
        string Id { get; set; }
        bool IsParent { get; set; }
    }
    
    public class Parent : IMyClass
    {
        public string Id { get; set; }
        public bool IsParent { get; set; }
        public string ParentName { get; set; }
    
        public Parent()
        {
            IsParent = true;
        }
    }
    
    public class Child : IMyClass
    {
        public string Id { get; set; }
        public bool IsParent { get; set; }
        public string ChildName { get; set; }
    
        public Child()
        {
            IsParent = false;
        }
    }
    

    运行此程序将创建一个名为 myChildren 的子列表和一个名为 myParents 的父列表。

    接口只需要一个属性,bool IsParent 属性。通过它,GetSomeValue 方法可以构建适当的父或子,然后返回一个枚举列表,然后可以将其强制转换为适当的类型。

    【讨论】:

      【解决方案4】:

      您可以按如下方式使用 Generic

          public static List<T> GetSomeValue<T>(string id)
          {
              return (typeof(T) == typeof(Child)) ? BuildChildResult(id) as List<T> : BuildParentResult(id) as List<T>;
          }
      

      那么你可以这样称呼它

              var childList = GetSomeValue<Child>("");
              var parentList = GetSomeValue<Parent>("");
      

      【讨论】:

        【解决方案5】:

        应该这样做

        IEnumerable<parent> GetSomeValue(string id, boolean needChild) {  
          ......  
          if (needChild)  
            return BuildChildResult(id);  
          else  
            return BuildParentResult(id);  
        }  
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-17
        • 1970-01-01
        • 2015-02-04
        相关资源
        最近更新 更多