【问题标题】:Can I use generic getter/setter methods on multiple lists of same base types in C#我可以在 C# 中相同基类型的多个列表上使用通用 getter/setter 方法吗
【发布时间】:2018-10-24 22:31:19
【问题描述】:

我想知道是否有一种方法可以为以下代码创建通用的 getter 和 setter 方法。

目前,setter 检查输入对象的实际类型并将其添加到相关列表中。对我来说这感觉是一种糟糕的方法,但我想知道是否有更好的方法。

我不能使用任何其他数据结构,如字典,因为我使用的序列化系统只能序列化简单的集合类型,如列表和数组,因此是所有单独的列表。

public abstract class BaseStyleType {}
public class ImageStyle  : BaseStyleType {}
public class TextStyle   : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc

public class GlobalStyle : ASerializedObject
{
    public List<ImageStyle>  ImageStyles     = new List<ImageStyle>();
    public List<TextStyle>   TextStyles      = new List<TextStyle>();
    public List<ButtonStyle> ButtonStyles    = new List<ButtonStyle>();
    //... etc

    // Setter
    public void SetStyle(BaseStyleType inStyle)
    { 
        if (inStyle as ImageStyle != null)
            ImageStyles.Add((ImageStyle)inStyle);
        else if (inStyle as TextStyle != null)
            TextStyles.Add((TextStyle)inStyle);
        else if (inStyle as ButtonStyle != null)
            ButtonStyles.Add((ButtonStyle)inStyle);
        //... etc
    }

    // Getter
    public T GetStyle<T>(int index)
    {
        //...?
    }
}

谢谢

【问题讨论】:

标签: c# list class generics member


【解决方案1】:

不应仅仅因为您不能将事物用于序列化目的而阻止您实际使用它们。

以下解决方案的优点是您可以从 BaseStyleType(或其他超类型)无限创建派生类,并且您只需创建属性即可访问字典。

public abstract class BaseStyleType {}
public class ImageStyle  : BaseStyleType {}
public class TextStyle   : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}

// NOT THREAD SAFE
public class GlobalStyle
{
   // 
   private Dictionary<Type,List<BaseStyleType>> _lists = 
     new Dictionary<Type,List<BaseStyleType>>();

   // Not sure why you'd use Fields here...
   public IEnumerable<ImageStyle> ImageStyles
   {
     get 
     {
       IEnumerable<ImageStyle> result = null;
       List<BaseStyleType> list;
       if (_lists.TryGetValue(typeof(ImageStyle), out list))
       {
         result = list.Cast<ImageStyle>();
       }
       return result;
     }
   }
   //etc
   //public List<ImageStyle>  ImageStyles     = new List<ImageStyle>();
   //public List<TextStyle>   TextStyles      = new List<TextStyle>();
   //public List<ButtonStyle> ButtonStyles    = new List<ButtonStyle>();


   // Setter
   public void SetStyle<T>(T inStyle)
       where T : BaseStyleType
   {
       List<BaseStyleType> list;
       if (_lists.TryGetValue(typeof(T), out list))
       {
         list.Add(inStyle);
       }
       else
       {
           list = new List<BaseStyleType>();
           list.Add(inStyle);
           _lists.Add(typeof(T), list);
       }
   }
}

【讨论】:

    【解决方案2】:

    我至少看到了两种方式:

    1) 你有一个简单、扁平的层次结构。只列出 BaseStyleType。让协方差和自动向上转换处理细节。

    2) 像这样修改你的代码:

    public abstract class BaseStyleType {}
    public class ImageStyle  : BaseStyleType {}
    public class TextStyle   : BaseStyleType {}
    public class ButtonStyle : BaseStyleType {}
    //...etc
    
    public class GlobalStyle <List1Type, List2Type, List3Type, ... > : ASerializedObject
    {
        public List<List1Type>  ImageStyles     = new List<List1Type>();
        public List<List2Type>   TextStyles      = new List<List2Type>();
        public List<List3Type> ButtonStyles    = new List<List3Type>();
        //... etc
    
        // Setter
        public void SetStyle(BaseStyleType inStyle)
        { 
            if (inStyle as ImageStyle != null)
                ImageStyles.Add((ImageStyle)inStyle);
            else if (inStyle as TextStyle != null)
                TextStyles.Add((TextStyle)inStyle);
            else if (inStyle as ButtonStyle != null)
                ButtonStyles.Add((ButtonStyle)inStyle);
            //... etc
        }
    
        // Getter
        public T GetStyle<T>(int index)
        {
            //...?
        }
    }
    

    长类型列表的问题是你最终不得不使用像 GlobalStyle &lt;ImageStyle , TextStyle, ButtonStyle&gt;单次 次需要该类型(字段类型、返回类型、参数等)。从两个通用占位符开始,创建类型别名通常是个好主意。

    using CustomGlobalStyle = GlobalStyle <ImageStyle, TextStyle, ButtonStyle>;
    

    【讨论】:

    • 我认为这不会编译,您无法将通用约束绑定到您的 BaseStyleType 实现,因此您的列表将拒绝显式转换的对象因为无法转换。
    • @JonathonChase:我不知道该代码中的任何地方有任何显式转换。我只说“有点像那样”,承认它不是正确可操作的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多