【问题标题】:Is it possible to wrap integer and call it like integer?是否可以包装整数并将其称为整数?
【发布时间】:2011-03-27 19:33:37
【问题描述】:

我想让 IDictionary<int, Driver> 中的 int 对其含义不那么晦涩,所以我认为将其包装起来可能是个好主意。结果将类似于IDictionary<finishPosition, Driver>

最好,finishPosition 应该像 finishPosition = 1 这样分配。

我不知道这是否可能以及如何。

【问题讨论】:

    标签: c# c#-4.0


    【解决方案1】:

    您可以使用 struct 进行隐式转换。

    public struct FinishPosition {
        public readonly int Position;
    
        public FinishPosition(int position) {
            this.Position = position;
        }
    
        public static implicit operator FinishPosition(int position) {
            return new FinishPosition(position);
        }
    }
    
    
    // ...
    
    Dictionary<FinishPosition, Driver> dict = new Dictionary<FinishPosition, Driver>();
    Driver bob = new Driver();
    
    // The following two lines are effectively equivalent
    dict[new FinishPosition(7)] = bob;
    dict[7] = bob;
    
    // So are these two
    bob = dict[7];
    bob = dict[new FinishPosition(7)]
    

    【讨论】:

    • 这显然是比我更好的解决方案。到目前为止,不那么令人困惑。
    • 看起来是正确的,问了什么,但这是相当多的开销......为了可读性(和安全),我会省略隐式转换。
    • @Henk:这里的重点是隐式转换;当它仅以一种方式工作时,它不会像您想象的那样严重损害可读性。
    • @Config:是的,它被要求。但它确实直接影响了可读性。问题有冲突。
    • @Henk:确实,隐式转换在某些情况下会严重损害可读性,但在其他情况下也会有所帮助。例如,如果你有两种方式的隐式转换,有时会很混乱。但是对于像这样的包装器,它非常方便,并且不会以任何方式降低可读性。
    【解决方案2】:

    当然,只要使用这个 using 指令:

    using FinishPosition = System.Int32;

    在源文件的顶部,并像在示例中一样编写代码。

    如果您像这样使用 using 指令,FinishPosition 是一个 int,其他文件会将其视为一个 int - 没有定义新类型 FinishPosition(感谢 cmets 中的配置器)。

    【讨论】:

    • 太棒了!你知道这个技巧在 VB.NET 中是否有等价物吗?
    • 刚刚试过,它也可以在 VB.NET 中运行。导入 myValue = System.Int32
    • 呃...不,它没有。问题可能是FinishPosition 一个Int32 并且其他文件会将其视为int。但它不会“隐藏”它或类似的东西......为什么会这样?
    • 哈哈好吧,那只是因为我错过了using System。 /facepalm :P 我会编辑我的答案。这将教我用 Notepad++ 而不是 VS 编写测试代码。
    • 这是一种可能令人困惑的做法。它仍然是一个整数。任何文档都会说它是一个它(它在源文件中简单地称为 so Else。编译时信息完全消失,不同文件中的智能感知应将其报告为 int。语法旨在消除歧义
    【解决方案3】:

    你可以使用枚举:

    enum Position { Finish, Some, Other }
    
    IDictionary<Position, Driver> lookup = ...;
    
    Driver d = lookup[Position.Finish];
    

    【讨论】:

    • 也许我理解错了(或者相反)-但是finishPosition应该可以分配不同种类的整数,比如finishPosition = 1,finishPosition = 2,finishPosition = 3,并分配每个这些带有该位置的 Driver 对象 - 并将它们存储在字典中。字典将是司机和他们完成的位置。
    • 最好的办法是命名这些整数(一些,其他),但您也可以分配一个任意的 int 值。也许我把你的名字弄错了,适应。
    • 您不能将任意整数分配给枚举变量。仅 0enum 值,或显式转换。
    • @config:在显式演员表上是。
    • 感谢您的回答,尽管我仍在努力解决它:-)
    【解决方案4】:

    在我看来,在将通用值用于特定意图的任何地方都可以使用 AbstractDataType 模式(这种情况已由许多其他人提出,例如 Percentage、ReadonlyString、ConnectionString 等)

    注意,我个人认为,与它们进行隐式转换有点把整个事情都掏空了(通过隐式转换,编译器不再保证在正确的地方以特定意图使用泛型值) .

    下面的示例应该会激发您按照自己的方式进行操作:您仍然可以选择自己喜欢的便利程度/详细程度。它展示了两种方法:

    • _byInt 按 PseudoInt 索引字典
    • _byEnum 按 Enum 索引字典:int 类型

    注意事项

    事不宜迟:

    #define IMPLICIT_CONVERSIONS
    using System.Collections.Generic;
    
    namespace NS
    {
        public enum PositionEnum : int { Begin = 0, Normal = 1, End = 99 }
    
        public struct Pseudo<T> where T : struct
        {
            public T Value;
            public Pseudo(T value) { Value = value; }
    #if IMPLICIT_CONVERSIONS
            public static implicit operator T(Pseudo<T> pi)  { return pi.Value; }
            public static implicit operator Pseudo<T>(T ni)  { return new Pseudo<T>(ni); }
    #endif
        }
    
        static class Program
        {
            private static Pseudo<T> AsPseudo<T>(this T value) where T : struct
            {
                return new Pseudo<T>(value);
            }
    
            private static readonly IDictionary<Pseudo<int>, string> _byInt = 
                new Dictionary<Pseudo<int>, string>()
                    {   { 0,  "aap" },
                        { 1,  "noot" },
                        { 99, "mies" },
                    };
    
            private static readonly IDictionary<Pseudo<PositionEnum>, string> _byEnum = 
                new Dictionary<Pseudo<PositionEnum>, string>()
                    {   { PositionEnum.Begin,  "aap" },
                        { PositionEnum.Normal, "noot" },
                        { PositionEnum.End,    "mies" },
                    };
    
            public static void Main(string[] args)
            {
                string s;
                s = _byInt[0];
                s = _byEnum[PositionEnum.Normal];
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      我刚刚在 [1] 之前链接的问题中调整了 RichEnum 通用基类

      我想说我更喜欢这种方法,因为从长远来看,它确实看起来最灵活。实际上,我能想到的唯一缺点是 RichEnum 类型不再是值类型。

      去看看我的意思(再次包括一个完全运行的示例):

      [1]Can we define implicit conversions of enums in c#?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-11
        • 2021-07-24
        • 1970-01-01
        • 2018-03-18
        • 1970-01-01
        • 2012-02-12
        • 2012-04-19
        相关资源
        最近更新 更多