[Canonical page](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/candidate/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Candidate

One alternative edit to score: an id and the [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>) to try. Build a list of candidates with object initializers and pass it to [`Project.Evaluate`](<https://docs.dhtmlx.com/planning-engine/net/api/project-evaluate.md>) or [`Project.EvaluateWith`](<https://docs.dhtmlx.com/planning-engine/net/api/project-evaluate.md#evaluatewith>).

## Declaration

```csharp
namespace Plen;

public sealed class Candidate : IDeepCloneable<Candidate>
```

Both properties are `required`, so `new Candidate()` without `Id` and `Changes` doesn't compile.

## Properties

| Property | Type | Description |
|---|---|---|
| `Id` | [`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | Label for the candidate. Copied unchanged into [`CandidateResult.Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/candidate-result.md>). Uniqueness isn't checked. |
| `Changes` | [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>) | Edits to apply to the copy before scheduling it. An empty change set scores the plan as it is. |

A `string`, `int` or `double` converts to `Id` implicitly.

For how a stale `Changes.BaselineId` or a rejected operation in `Changes` is reported, see [`Project.Evaluate`](<https://docs.dhtmlx.com/planning-engine/net/api/project-evaluate.md#errors>) and [`CandidateResult.Error`](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/candidate-result.md>).

## Methods

### DeepClone

```csharp
public Candidate DeepClone()
```

Returns a deep copy: `Changes` and every list in it are copied, nothing is shared with the original.

### ToString

```csharp
public override string ToString()
```

Returns a readable rendering of `Id` and `Changes`, for logging.

`Candidate` doesn't override `Equals`; two instances compare by reference.

## Example

Score two ways to staff task `1`: assign `dev1` or assign `dev2`.

```csharp
using Plen;

var monday = Moment.FromYmdHm(2026, 8, 10, 8, 0)
    ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks = [new TaskData(1) { StartDate = monday, Duration = 2.0 }],
    Resources = [new ResourceData { Id = "dev1" }, new ResourceData { Id = "dev2" }],
};

var project = new Project();
project.Solve(data, new SolveOptions());

var candidates = new List<Candidate>();
foreach (var dev in new[] { "dev1", "dev2" })
{
    var changes = new SchedulingChanges();
    changes.Assignments.Add.Add(new AssignmentData { Task = 1, Resource = dev, Value = 1.0 });
    candidates.Add(new Candidate { Id = dev, Changes = changes });
}

var result = project.Evaluate(candidates, new EvaluateOptions());
foreach (var c in result.Candidates)
    Console.WriteLine($"{c.Id}: cost {c.Cost}");
```

## Related

- [`Project.Evaluate`](<https://docs.dhtmlx.com/planning-engine/net/api/project-evaluate.md>) - the call that scores a list of candidates
- [`SchedulingChanges`](<https://docs.dhtmlx.com/planning-engine/net/api/core/changes/scheduling-changes.md>) - the change set a candidate carries
- [`CandidateResult`](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/candidate-result.md>) - the score returned for each candidate
- [`EvaluateOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/evaluate/evaluate-options.md>) - leveling stage, focus tasks and baseline guard
- [Evaluating alternatives](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/evaluating-alternatives.md>) - building candidates and comparing them
