When using XML Documentation Comments, I can't figure out how I can refer to another class member. Take this code:
TGreeter = class
/// <summary>Says hello</summary>
procedure Hello;
/// <summary>Says hello to all</summary>
/// <remarks>
/// This is the same as <see cref="Hello"/>, but it says hello to all
/// instead.
/// </remarks>
procedure HelloAll;
end;
Help Insight displays the help for HelloAll fine, but if I click on the link to Hello it does nothing (almost nothing; the mouse pointer indicates that, for a second or so, it does some thinking, but then it stops). What is the correct way to make such a cross-reference?
I was wondering myself for quite a long time before I found a syntax that works (tested with Delphi XE4): You need to put the unit name, a pipe, the class name, a point and then method name.
In your example, let's say that the unit is called "MyUnit", then you should use:
<see cref="MyUnit|TGreeter.Hello"/>
Related
Seems a simple task but despite google and looking at all the menus I cannot find how to look at documentation of classes or objects in XNA.
In unity you just press ctrl and ' what is is in visual c#/XNA? I am looking for information on created classes/Objects not the online documentation/Help.
You can search the MSDN for the required information. For example, here is a link for the SpriteBatch class.
The MSDN is not just limited to XNA, it is a useful tool for all Microsoft based languages.
Please note that some of the XNA documentation is not very informative. I've come across pages on XNA functionality that contain only one or two lines - no example code either!
What about classes that people have created and documented?
The author of the code will need to provide documentation in the code. Here is an example:
/// <summary>
/// This is an example of XML documentation for a class.
/// </summary>
class Program
{
/// <summary>
/// This is an example of XML documentation for a public method.
/// </summary>
/// <param name="name">The name we are validating.</param>
/// <returns>True if valid, otherwise false.</returns>
public bool IsValid(string name)
{
return true;
}
}
Visual Studio will automatically generate most of the XML for you. Just type "///" above the class/method to begin. You can read more on it here.
You will now be able to view the code documentation by hovering over the class/function name.
To anyone who might get this problem in the future - I have solved it.
The files are .chm files and are located in the folder of the classes when available.
Another issue when you are downloading them from another computer to be aware of is they are sometimes blocked.
If that is the case - right click them/properties/general and in the lower right corner there is a button (Unblock) click this, reload the .chm file and all should be readable.
So glad I found this I was starting to question my sanity and it appeared no one else was aware of them or at least understood my problem.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Code documentation for delphi similar to javadoc or c# xml doc
I have been utilizing the Documentation capabilities of RAD Studio Delphi XE2 across most of my global source (libraries such as business rules, components/controls, etc.). This places some commented text just before the declaration of various things in your source code, like so:
type
/// <summary>
/// This class is used for this and that.
/// </summary>
TMyObject = class(TObject)
....
or even
/// <summary>
/// This function does this and that.
/// </summary>
/// <returns>
/// This is the result of what DoSomething produces.
/// </returns>
/// <remarks>
/// DoSomething is only a sample function for demonstration purposes.
/// </remarks>
function DoSomething: String;
The main reason I've been doing this is so that when you hover over a symbol, when it shows the insight, it will include this documentation text with it. For example, in a completely separate unit, hover over the text DoSomething wherever it's used and it will show you a hint box containing the exact text written in this documentation.
Hint: press either Ctrl+Shift+D or Ctrl+Alt+D (I've seen both those on different PC's) and it will open a window to make things easier. I stumbled across this when pressing Ctrl+Shift+S to save but accidentally hit D.
What I would like to know is how can I export this documentation to a CHM help file? I would like to make a help file linked to my library so a developer can use F1 in the code and see an explanation of what the code does. Just like the standard Delphi source documentation (and most other languages).
It's not a CHM file but if you use Delphi Enterprise or higher the IDE has the ability to produce documentation using your properly formatted source code comments.
I am playing with code documentation and live templates and I quite don't get it.
I've read Dr.Bob's article about generating documentation and wiki articles about live templates but I have one problem with class description.
By class description I understand the IDE behaviour when I point my mouse cursor over class declaration.
For example, I have such class with it's description:
type
{$REGION 'TMyClass'}
/// <summary>
/// Summary works
/// </summary>
/// <remarks>
/// Remarks works
/// </remarks>
/// <exception cref="www.some.link">This works</exception>
/// <list type="bullet">
/// <item>
/// <description>description does not work</description>
/// </item>
/// <item>
/// <description>description does not work</description>
/// </item>
/// </list>
/// <permission cref="www.some.link">This works</permission>
/// <example>
/// <code>
/// Code example does not work
/// </code>
/// </example>
{$ENDREGION}
TMyClass = class
private
a, b, c: Integer;
public
end;
And later in the code I have such declaration:
var
MyObject: TMyClass;
When I put mouse cursor over the class type I have such description:
As you see not every html tag was rendered by the IDE engine. I would really want to know how to render additional tags, especially tag with code example. Is it possible?
I am using Delphi 2009 Proffesional.
Only limited set of tags is supported. The best documentation about this stuff I'm aware of is the DevJET Software's Delphi Documentation Guidelines (at the end of the "Table of Contents" there is link to the PDF).
The tags Help Insight supports are described in the online help and the Delphi docwiki. They are a subset of the tags C#'s help tags support. No other tags than the ones listed on the Embarcadero site seem to be supported (I have tried them). The only other things that work (and are required) are "<", ">" and """.
Update
There seem to be some products that allow you to use the full syntax as e.g. described in the Delphi Documentation Guidelines linked to by #ain. But that requires you to buy a commercial product like DevJet's Documentation Insight, which should not be confused with the Help Insight the IDE supports since Delphi 2006.
As you found out, and I did too, only the subset described in the Delphi docwiki is supported by the bare IDE without commercial products. There is also the documentation that is supported by the Modelling interface, but that is different again. In the normal IDE, you can only use the tags you and I already found.
I've read the official documentation and I understand what class references are but I fail to see when and why they are best solution compared to alternatives.
The example cited in the documentation is TCollection which can be instantiated with any descendant of TCollectionItem. The justification for using a class reference is that it allows you to invoke class methods whose type is unknown at compile time (I assume this is the compile time of TCollection). I'm just not seeing how using TCollectionItemClass as an argument is superior to using TCollectionItem. TCollection would still be able to hold any descendant of TCollectionItem and still be able to invoke any method declared in TCollectionItem. Wouldn't it?
Compare this with a generic collection. TObjectList appears to offer much the same functionality as TCollection with the added benefit of type safety. You are freed from the requirement to inherit from TCollectionItem in order to store your object type and you can make a collection as type specific as you want. And if you need to access item's members from within the collection you can use generic constraints. Other than the fact that class references are available to programmers prior to Delphi 2009 is there any other compelling reason to use them over generic containers?
The other example given in the documentation is passing a class reference to a function that acts as an object factory. In this case a factory for creating objects of type TControl. Its not really apparent but I'm assuming the TControl factory is invoking the constructor of the descendant type passed to it rather than the constructor of TControl. If this is the case then I'm starting to see at least some reason for using class references.
So I guess what I'm really trying to understand is when and where class references are most appropriate and what do they buy a developer?
MetaClasses and "class procedures"
MetaClasses are all about "class procedures". Starting with a basic class:
type
TAlgorithm = class
public
class procedure DoSomething;virtual;
end;
Because DoSomething is a class procedure we can call it without an instance of TAlgorithm (it behaves like any other global procedure). We can do this:
TAlgorithm.DoSomething; // this is perfectly valid and doesn't require an instance of TAlgorithm
Once we've got this setup we might create some alternative algorithms, all sharing some bits and pieces of the base algorithm. Like this:
type
TAlgorithm = class
protected
class procedure DoSomethingThatAllDescendentsNeedToDo;
public
class procedure DoSomething;virtual;
end;
TAlgorithmA = class(TAlgorithm)
public
class procedure DoSomething;override;
end;
TAlgorithmB = class(TAlgorithm)
public
class procedure DoSomething;override;
end;
We've now got one base class and two descendent classes. The following code is perfectly valid because we declared the methods as "class" methods:
TAlgorithm.DoSomething;
TAlgorithmA.DoSomething;
TAlgorithmB.DoSomething;
Let's introduce the class of type:
type
TAlgorithmClass = class of TAlgorithm;
procedure Test;
var X:TAlgorithmClass; // This holds a reference to the CLASS, not a instance of the CLASS!
begin
X := TAlgorithm; // Valid because TAlgorithmClass is supposed to be a "class of TAlgorithm"
X := TAlgorithmA; // Also valid because TAlgorithmA is an TAlgorithm!
X := TAlgorithmB;
end;
TAlgorithmClass is a data type that can be used like any other data type, it can be stored in a variable, passed as a parameter to a function. In other words we can do this:
procedure CrunchSomeData(Algo:TAlgorithmClass);
begin
Algo.DoSomething;
end;
CrunchSomeData(TAlgorithmA);
In this example the procedure CrunchSomeData can use any variation of the algorithm as long as it's an descendant of TAlgorithm.
Here's an example of how this behavior may be used in a real-world application: Imagine a payroll-type application, where some numbers need to be calculated according to an algorithm that's defined by Law. It's conceivable this algorithm will change in time, because the Law is some times changed. Our application needs to calculate salaries for both the current year (using the up-to-date calculator) and for other years, using older versions of the algorithm. Here's how things might look like:
// Algorithm definition
TTaxDeductionCalculator = class
public
class function ComputeTaxDeduction(Something, SomeOtherThing, ThisOtherThing):Currency;virtual;
end;
// Algorithm "factory"
function GetTaxDeductionCalculator(Year:Integer):TTaxDeductionCalculator;
begin
case Year of
2001: Result := TTaxDeductionCalculator_2001;
2006: Result := TTaxDeductionCalculator_2006;
else Result := TTaxDeductionCalculator_2010;
end;
end;
// And we'd use it from some other complex algorithm
procedure Compute;
begin
Taxes := (NetSalary - GetTaxDeductionCalculator(Year).ComputeTaxDeduction(...)) * 0.16;
end;
Virtual Constructors
A Delphi Constructor works just like a "class function"; If we have a metaclass, and the metaclass knows about an virtual constructor, we're able to create instances of descendant types. This is used by TCollection's IDE Editor to create new items when you hit the "Add" button. All TCollection needs to get this working is a MetaClass for a TCollectionItem.
Yes a Collection would still be able to hold any descendant of TCollectionItem and to invoke methods on it. BUT, it wouldn't be able to instantiate a new instance of any descendant of a TCollectionItem. Calling TCollectionItem.Create constructs an instance of TCollectionItem, whereas
private
FItemClass: TCollectionItemClass;
...
function AddItem: TCollectionItem;
begin
Result := FItemClass.Create;
end;
would construct an instance of whatever class of TCollectionItem descendant is held in FItemClass.
I haven't done much with generic containers, but I think that given a choice, I would opt for the generic container. But in either case I'd still have to use a metaclass if I wanted to have the list instantiate and do whatever else needs to be done when an item is added in the container and I do not know the exact class beforehand.
For example an observable TObjectList descendant (or generic container) could have something like:
function AddItem(aClass: TItemClass): TItem;
begin
Result := Add(aClass.Create);
FObservers.Notify(Result, cnNew);
...
end;
I guess in short the advantage/benefit of metaclasses is any method/class having only knowledge of
type
TMyThing = class(TObject)
end;
TMyThingClass = class of TMyThing;
is able to construct instances of any descendant of TMyThing whereever they may have been declared.
Generics are very useful, and I agree that TObjectList<T> is (usually) more useful than TCollection. But class references are more useful for different scenarios. They're really part of a different paradigm. For example, class references can be useful when you have a virtual method that needs to be overridden. Virtual method overrides have to have the same signature as the original, so the Generics paradigm doesn't apply here.
One place where class references are used heavily is in form streaming. View a DFM as text sometime, and you'll see that every object is referred to by name and class. (And the name is optional, actually.) When the form reader reads the first line of an object definition, it gets the name of the class. It looks it up in a lookup table and retrieves a class reference, and uses that class reference to call that class's override of TComponent.Create(AOwner: TComponent) so it can instantiate the right kind of object, and then it starts applying the properties described in the DFM. This is the sort of thing that class references buy you, and it can't be done with generics.
I also would use a metaclass whenever I need to be able to make a factory that can construct not only one hard-coded class, but any class that inherits from my base class.
Metaclasses are not the term I am familiar with in Delphi circles however. I believe we call them class references, which has a less "magic" sounding name, so it's great that you put both common monikers in your question.
A concrete example of a place I have seen this used well is in the JVCL JvDocking components where a "docking style" component provides metaclass information to the base docking component set, so that when a user drags their mouse and docks a client form to the docking host form, the "tab host" and "conjoin host" forms that show grabber bars (similar in appearance to the title bar of a regular undocked window) can be of a user-defined plug-in class, that provides a customized appearance and customized runtime functionality, on a plug-in basis.
In some of my applications I have a mechanism that connects classes to forms capable of editing instances of one or more of that classes. I have a central list where those pairs are stored: a class refernce and a form class reference. Thus when I have an instance of a class I can lookup the corresponding form class, create a form from it and let it edit the instance.
Of course this could also be implemented by having a class method returning the appropriate form class, but that would require the form class to be known by the class. My approach makes a more modular system. The form must be aware of the class, but not the other way round. This can be a key point when you cannot change the classes.
In the unit below I have a variable declared in the IMPLEMENTATION section - local to the unit. I also have a procedure, declared in the TYPE section which takes an argument and assigns that argument to the local variable in question. Each instance of this TFrame gets passed a unique variable via passMeTheVar.
What I want it to do is for each instance of the frame to keep its own version of that variable, different from the others, and use that to define how it operates. What seems to be happening, however, is that all instances are using the same value, even if I explicitly pass each instance a different variable.
ie:
Unit FlexibleUnit;
interface
uses
//the uses stuff
type
TFlexibleUnit=class(TFrame)
//declarations including
procedure makeThisInstanceX(passMeTheVar:integer);
private
//
public
//
end;
implementation
uses //the uses
var myLocalVar;
procedure makeThisInstanceX(passMeTheVar:integer);
begin
myLocalVar:=passMeTheVar;
end;
//other procedures using myLocalVar
//etc to the
end;
Now somewhere in another Form I've dropped this Frame onto the Design pane, sometimes two of these frames on one Form, and have it declared in the proper places, etc. Each is unique in that :
ThisFlexibleUnit : TFlexibleUnit;
ThatFlexibleUnit : TFlexibleUnit;
and when I do a:
ThisFlexibleUnit.makeThisInstanceX(var1); //want to behave in way "var1"
ThatFlexibleUnit.makeThisInstanceX(var2); //want to behave in way "var2"
it seems that they both share the same variable "myLocalVar".
Am I doing this wrong, in principle? If this is the correct method then it's a matter of debugging what I have (which is too huge to post) but if this is not correct in principle then is there a way to do what I am suggesting?
EDIT:
Ok, so the lesson learned here is that the class definition is just that. Many classes can go in one unit and all instances of all classes in the Type section share the implementation section of the unit.
myLocalVar is a global variable, but only visible within the unit.
A local variable would be in a procedure/function, like
procedure makeThisInstanceX(passMeTheVar: integer);
var
myLocalVar: Integer;
begin
myLocalVar := passMeTheVar;
end;
if you want an instance variable, that is each frame has its own copy, put it in the class:
type
TFlexibleUnit = class(TFrame)
procedure makeThisInstanceX(passMeTheVar:integer);
private
myLocalVar: Integer;
...
end;
You are calling the makeThisInstanceX method as a class (static) method rather than creating an instance of the class and calling it as an object method. Take a look at this reference:
http://oreilly.com/catalog/delphi/chapter/ch02.html
frame / unit / class / control
I applaud your heroic attempt to better the code. However, judging by your questions and comments I regret to inform you that your understanding is very limited.
A frame is not a unit which is not a class. A frame is a class but not every class is a frame. A frame is a control but not every control is a frame. Units have interface and implementation (and initialization and finalization) sections. Classes have private and public (and protected and published) parts.
I did not put the last paragraph in to try to teach but to allow you to gauge your understanding level. A Delphi developer ought to have no problem with the paragraph. I'm not trying to make you feel bad or to show off - just trying to help. Perhaps Stack Overflow is not the right tool for you at this time.
As somebody just learning Delphi for the first time, I might be confused by some of the seemingly redundant features. But the product has a long history and each addition made sense at the time it was added. It was also easier to learn when you only had to learn it a piece at a time.