Delphi Generics>具有默认值的字典

fra*_*cis 5 delphi generics dictionary default

我希望有一个字典,当找不到搜索键时返回默认值.阅读文档:

Generics.Collections.Tdictionary [...]此类提供映射[...]和初始内容.

1 - 怎么样?有没有办法做到这一点ala Python:{1:'one'; 2:'两个'}?

Generics.Collections.TDictionary.TryGetValue [...]如果给定的键在字典中并在Value中提供其值,则TryGetValue返回true.否则,它返回false,并将Value设置为Tvalue的默认值类型.

2 - 如何设置此默认值?我找不到构造函数(可能我只是在错误的地方搜索过.我期待类似"构造函数Create(DefaultValue:TValue);")

所以我正在尝试实现自己的(可能没有必要.见上文):

代码是(欢迎评论和建议!):

unit Util;

interface

uses
    Generics.collections;

type

    //
    // Dictionary with default response
    //
    TDefaultDictonary<K, V> = class(TObjectDictionary<K, V>)
    private
        M_DefaultValue : V;

    public
        constructor Create(Defaultvalue : V);
        destructor Destroy; reintroduce;
        function GetDefaultValue : V;
        function TryGetValue(const Key: K; out Value: V): Boolean;
        function GetValueOf(const Key: K) : V;
    end;

implementation

//
// Contructor and destructor
//
constructor TDefaultDictonary<K, V>.Create(Defaultvalue : V);
begin
    inherited Create;

    M_DefaultValue := Defaultvalue;
end;

destructor TDefaultDictonary<K, V>.Destroy;
begin
    inherited Destroy;
end;

//
// Get the default Value
//
function TDefaultDictonary<K, V>.GetDefaultValue : V;
begin
    Result := M_DefaultValue;
end;


//
// Try to get a value from the dictionary for the given key.
//
// If the value is found then "Value" holds it and the function returns true.
// If the value is not found then "Value" holds the default value and the
// function returns false.
//
function TDefaultDictonary<K, V>.TryGetValue(const Key: K; out Value: V): Boolean;
var
    IsKeyFound : boolean;
    DictVal : V;

begin
    IsKeyFound := inherited TryGetValue(Key, DictVal);
    if not IsKeyFound then begin
        DictVal := M_DefaultValue;
    end;

    // Outputs:
    Value := DictVal;
    Result := IsKeyFound;
end;


//
// Get a value from the dictionary for the given key.
//
// If the value is found then the function returns it.
// If the value is not found the function returns the default value.
//
function TDefaultDictonary<K, V>.GetValueOf(const Key: K) : V;
var
    DictVal : V;

begin
    TryGetValue(Key, DictVal);

    Result := DictVal;
end;
Run Code Online (Sandbox Code Playgroud)

测试是:

unit Test_Utils;
{
    Test the TDefaultDictionary functionality
}

interface

uses
    Sysutils, Math, TestFramework, Util;

type

    TestUtil = class(TTestCase)

    public
        procedure SetUp; override;
        procedure TearDown; override;

    published
        procedure TestDefaultDictionaryGetDefaultResponse;
        procedure TestDefaultDictionaryExistingKey;
        procedure TestDefaultDictionaryNotExistingKey;

    end;


implementation


procedure TestUtil.SetUp;
begin
end;

procedure TestUtil.TearDown;
begin
end;


procedure TestUtil.TestDefaultDictionaryGetDefaultResponse;
var
    dd : TDefaultDictonary<integer, string>;

begin
    dd := TDefaultDictonary<integer, string>.Create('Default response');
    checkEquals('Default response', dd.GetDefaultValue);

    dd.Free;
end;

procedure TestUtil.TestDefaultDictionaryExistingKey;
var
    dd : TDefaultDictonary<integer, string>;
    outVal : string;
    isKeyFound : boolean;

begin
    dd := TDefaultDictonary<integer, string>.Create('Default response');
    dd.Add(1, 'My one');

    checkEquals(1, dd.Count,
        'One element as count');

    isKeyFound := dd.TryGetValue(1, outVal);
    check(isKeyFound,
        'Key not found by TryGetValue');

    checkEquals('My one', outVal,
        'Value given by TryGetValue');  

    checkEquals('My one', dd[1],
        'Value given by indexing as array');

    dd.Free;
end;


procedure TestUtil.TestDefaultDictionaryNotExistingKey;
var
    dd : TDefaultDictonary<integer, string>;
    outVal : string;
    isKeyFound : boolean;

begin
    dd := TDefaultDictonary<integer, string>.Create('Default response');
    dd.Add(1, 'one');

    isKeyFound := dd.TryGetValue(2, outVal);
    check(not isKeyFound,
        'Key should not be found by TryGetValue');

    checkEquals('Default response', outVal,
        'Default Value given by TryGetValue');

    checkEquals('Default response', dd.GetValueOf(2),
        'Default Value given by indexing as array');

    //
    // It is possible to oveload the indexer operator?
    // Please review or delete me !
    //
    //checkEquals('Default response', dd[2],
    //        'Value given by indexing as array');
    //

    dd.Free;
end;


initialization
    RegisterTest(TestUtil.Suite);
end.
Run Code Online (Sandbox Code Playgroud)

这远非完整.我想让索引器操作员也工作(参见最后一个测试).这有可能吗?还应该实施什么?

这个实现是否泄漏了M_DefaultValue(我是Delphi的新手).我不能在析构函数中做一些M_DefaultValue.Free(由于构造函数约束而不是那么灵活)这里可以做什么?

提前致谢,

弗朗西斯

Jer*_*ers 1

在自己编写所有这些代码之前,您可能需要查看DeHL 库中的通用类。

它支持这个:

类型支持概念,为每个内置 Delphi 类型定义一组默认“支持类”(用作集合中的默认值)。可以为您的自定义数据类型注册自定义“类型支持”类。

——杰罗恩