I think the answer is actually supposed to be C although the question sucks. Now I will justify both parts of that statement.
When I started using PostgreSQL, you could only do C through triggers and check constraints calling UDF's. Many of the database books I read recommended using triggers for referential integrity. It's nice that we have moved on but there are times and places where the limits of declarative referential integrity get in the way and one still ends up having to code constraint triggers by hand. Examples may include foreign keys based on derived information (internet address is in a stored CIDR block) or other cases where typical foreign key mechanisms are inadequate. The legacy of using triggers to manage referential integrity is thus not dead at all.
The question however is entirely inadequate because nobody in their right mind would hand-code procedural triggers where declarative referential integrity will work. You can do it. That doesn't mean it is a good substitute.
On some databases, like PostgreSQL, triggers require stored procedures and are therefore not a substitute for them. Similarly while I suppose it is theoretically possible to do something like a primary key using a trigger, typically this is done using an index instead.
Also I am going to disagree with Leigh above. Just because a trigger can be used to do a lot more than FKey checking doesn't mean that it isn't a historical and even current method to do this. It can be far broader but the use cases of triggers do include referential integrity enforcement and so a close, careful reading of the question suggests the answer is C and this is not contradicted by anything Leigh says above ;-).