【问题标题】:C# Struct / Lookup TableC#结构/查找表
【发布时间】:2011-05-08 11:18:32
【问题描述】:

假设我有一个声明如下的结构:

public struct Test
{
    public static int Width = 5;
    ...
    public static int[] Value = new int[1]{ 0 };
}

现在我想做的是从另一个结构中调用它,但我必须知道如何。我正在尝试做的事情(在我看来)如下所示:

public struct AnotherStruct
{
    public (type of struct) this[int key]
    {
        get
        {
            switch(key)
            {
                case 1:
                    return (another struct);
                default:
                    return null;
            }
        }
    }
}

我的最终目标是我想使用如下所示的代码,而不必创建对象的实例:

structobject s = new AnotherStruct[5];

所以这个“查找表”将在另一个项目中创建并构建,然后作为我的主项目中的 dll 调用。由于我在其他地方构建 dll 并调用它,我希望我可以将 dll 加载到内存中一次,然后我可以从我的主项目中引用该内存。然后我将分配一部分内存,我的代码将只引用它,避免创建此查找表的各个实例(从而避免分配内存和存储新实例所需的时间开销)。从长远来看,我节省的时间会非常有益,所以我希望我能以某种方式让它发挥作用。

我希望这不会太令人困惑,但如果需要任何澄清,请告诉我。

编辑 这是在网站上使用的,所以我真的需要一个在所有连接中持续存在的对象,并且在最初加载代码时创建一次。相同的想法,但也许这会带来更简单的解决方案?

【问题讨论】:

  • 看起来你需要一个工厂模式。
  • @Etienne de Martel 您能否创建一个简短的示例,说明从 dll 的角度和在主项目中如何工作。真的没有什么花哨的。我以前从未使用过工厂模式,我有限的研究表明它似乎相当复杂。
  • 细微差别:结构体是值类型,因此为了能够返回 null,您需要使用特殊的可空结构体类型 Nullable<Test>Test?
  • 我可以返回 null 以外的值,但感谢您的提醒。
  • 奇怪的是,您认为您需要一个 struct 来跨连接持续存在并且只创建一次。有许多更有效的方法来处理这个问题(在你的 global.asax.cs 的Application_Start(..) 中创建一个缓存在应用程序级别的单例。将​​结构用于这种通用目的可以是dangerous

标签: c# struct lookup-tables


【解决方案1】:

解决方案 #2。放弃整个 ID 的想法,只使用结构类型和泛型。

public struct St1 
{
}
public struct St2 
{
}

public class Factory<T>
    where T : struct
{
    static T _new = new T(); //cached copy of structure

    public static T New { get { return _new; } }        
}


class Program
{
    static void Main(string[] args)
    {
        St1 x1 = Factory<St1>.New;
        St1 x2 = Factory<St1>.New;
        St1 x3 = Factory<St1>.New;
        St2 y1 = Factory<St2>.New;
        St2 y2 = Factory<St2>.New;
    }
}

【讨论】:

    【解决方案2】:

    解决方案 #1。对所有结构和字典集合使用通用接口

    public interface IStr { }
    
    public struct St1 : IStr
    {
        public static int ID = 1;
    }
    public struct St2 : IStr
    {
        public static int ID = 2;
    }
    
    public class StructFactory : System.Collections.ObjectModel.KeyedCollection<int, IStr>
    {
        public static StructFactory Default = new StructFactory();
        protected override int GetKeyForItem(IStr item)
        {
            FieldInfo finfo = item.GetType().GetField("ID", 
                BindingFlags.Static | BindingFlags.Public);
    
            return (int)finfo.GetValue(item);
        }
    
        public StructFactory()
        {
            Add(new St1());
            Add(new St2());
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            St1 x = (St1)StructFactory.Default[1];
            St2 y = (St2)StructFactory.Default[2];
        }
    }
    

    【讨论】:

      【解决方案3】:

      上面使用的语法不起作用,因为它的意思是“创建一个包含五个元素的 AnotherStruct 数组”。但是,正如评论中提到的,您确实应该考虑使用工厂模式。

      但是,如果你真的想使用上面的模式,你可以稍微改变一下。让您的 AnotherStruct 数组保存每个结构的 Type 实例。然后,您的“创作”行看起来更像:

      structobject s = (structobject)Activator.CreateInstance(AnotherStruct[5]);
      

      您可以在程序集上使用反射(因为您将其包装在 DLL 中)来获取这些 Type 对象。

      最后,除非您有充分的理由使用struct(并且了解所有细微差别,其中有几个),否则请坚持使用class

      【讨论】:

        猜你喜欢
        • 2011-11-15
        • 1970-01-01
        • 1970-01-01
        • 2011-02-19
        • 2016-04-06
        • 1970-01-01
        • 1970-01-01
        • 2017-12-01
        • 1970-01-01
        相关资源
        最近更新 更多