Using Generic containers in Delphi XE - always?

2020-05-21 07:11发布

Generic containers can be a time saver when having a item, and a strongly typed list of those items. It saves the repetitive coding of creating a new class with perhaps a TList internal variable, and typed Add/Delete type methods, among other benefits (such as all the new functionality provided by the Generic container classes.)

However, is it recommended to always use generic containers for strongly typed lists going forward? What are the specific downsides of doing so? (If not worried about backwards compatibility of code.) I was writing a server application yesterday and had a list of items that I created 'the old way' and was going to replace it with a generic list but decided to keep it lean, but mostly out of habit. (Should we break the habit and start a new one by always using generics?)

7条回答
手持菜刀,她持情操
2楼-- · 2020-05-21 08:10

If you need polymoprhic lists then Generics are a hindrance, not a help. This does not even compile, for example, because you cannot use a TDogList where a TAnimalList is required:

  uses
    Generics.Collections;

  type
    TAnimal = class
    end;

    TDog = class(TAnimal)
    end;

    TAnimalList = TList<TAnimal>;
    TDogList = TList<TDog>;


  procedure FeedTheAnimals(const aList: TAnimalList);
  begin
    // Blah blah blah
  end;


  var
    dogs: TDogList;
  begin
    dogs := TDogList.Create;
    try
      FeedTheAnimals(dogs);

    finally
      dogs.Free;
    end;
  end;

The reasons for this are quite clear and easily explained, but it is just as equally counter intuitive.

My own view is that you can save a few seconds or minutes (if you are a slow typist) by using a generic instead of rolling a type safe container more specific and appropriate to your needs, but you may well end up spending more time working around the problems and limitations of Generics in the future than you saved by using them to start with (and by definition if you haven't been using generic containers up to now then you don't know what those problems/limitations might be until you run into them).

If I need a TAnimalList then the chances are I need or could benefit from additional TAnimal specific methods on that list class that I would like to inherit in a TDogList, which in turn may introduce additional specific members relevant to it's TDog items.

(Animal and Dog being used for illustrative purposes only, of course. I don't actually work on veterinarian code currently - LOL)

The problem is, you don't always know this at the start.

Defensive programming principles suggest (to me, ymmv) that painting yourself into a corner for the sake of a bit of time saving is likely to end up costing a lot in the future. And if it doesn't, the additional "cost" of not taking the up front saving is itself negligible.

Plus your code is more shareable with users of older Delphi versions, if you are inclined to be so generous.

:)

查看更多
登录 后发表回答