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


# Worker

A project resource that can be assigned, paired with its skill values. Workers go into [`Pool.Workers`](<https://docs.dhtmlx.com/planning-engine/net/api/assign/pool.md>), which [`SkillLayer.Slots`](<https://docs.dhtmlx.com/planning-engine/net/api/skill-layer-slots.md>) reads. Create one with an object initializer; `Resource` is `required`.

## Declaration

```csharp
namespace Plen.Assign;

public sealed class Worker : IDeepCloneable<Worker>, IEquatable<Worker>
```

## Properties

| Property | Type | Default | Description |
|---|---|---|---|
| `Resource` | [`Id`](<https://docs.dhtmlx.com/planning-engine/net/api/core/data/id.md>) | required | ID of a resource in the project's accepted state. When the worker matches a requirement, this ID goes into the slot's [`Allowed`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/slot.md>) list. |
| `Skills` | `List<`[`Skill`](<https://docs.dhtmlx.com/planning-engine/net/api/assign/skill.md>)`>` | empty | The worker's skill values, one `Skill` per skill ID. For how a skill missing from the list compares, see [`SkillMatch`](<https://docs.dhtmlx.com/planning-engine/net/api/assign/requirement.md#skillmatch>). |

## Methods

### DeepClone

```csharp
public Worker DeepClone()
```

Returns a deep copy. `Skills` and each [`Skill`](<https://docs.dhtmlx.com/planning-engine/net/api/assign/skill.md>) in it are copied, so nothing is shared with the original.

### Equals

```csharp
public bool Equals(Worker? other)
public override bool Equals(object? obj)
```

Two workers are equal when `Resource` is equal and `Skills` holds equal skills in the same order. `GetHashCode()` follows the same rule.

### ToString

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

Returns a readable rendering of `Resource` and `Skills`, for logging.

## Errors

An invalid worker makes [`SkillLayer.Slots`](<https://docs.dhtmlx.com/planning-engine/net/api/skill-layer-slots.md>) throw [`InputException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md>) with `Kind = `[`InputErrorKind.Validation`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md#inputerrorkind>). In the paths, `i` is the worker's index in the pool and `j` the skill's index. IDs compare by their text form, so `1` and `"1"` collide.

| `Path` | When | `Message` |
|---|---|---|
| `pool.workers[i].resource` | No resource with this ID in the accepted state. | `unknown resource "<id>"` |
| `pool.workers[i].resource` | An earlier worker in the pool names the same resource. | `duplicate worker "<id>"` |
| `pool.workers[i].skills[j].id` | The worker already lists this skill ID. | `duplicate skill "<id>"` |
| `pool.workers[i].skills[j].value` | The value is `NaN` or infinite. | `must be finite` |

## Example

```csharp
using Plen.Assign;

var pool = new Pool
{
    Workers =
    [
        new Worker
        {
            Resource = "ann",
            Skills =
            [
                new Skill { Id = "frontend", Value = 1 },
                new Skill { Id = "qa", Value = 2 },
            ],
        },
        // No skills: every skill counts as 0 for this worker.
        new Worker { Resource = "bob" },
    ],
};

Console.WriteLine($"{pool.Workers.Count} workers");
```

## Related

- [`Pool`](<https://docs.dhtmlx.com/planning-engine/net/api/assign/pool.md>) - the list of workers
- [`Skill`](<https://docs.dhtmlx.com/planning-engine/net/api/assign/skill.md>) - one skill value of a worker
- [`SkillLayer.Slots`](<https://docs.dhtmlx.com/planning-engine/net/api/skill-layer-slots.md>) - the call that matches workers to requirements
- [Skills and requirements](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/skills-and-requirements.md>) - describing who can do what
