# C# Code Style Guidelines

## Project Configuration

```xml
<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
  <Nullable>disable</Nullable>
  <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>


<ItemGroup>
  <Using Include="Dinaup.extensions" Static="true" />
</ItemGroup>

```

## Culture-Invariant by Design

Dinaup projects completely ignore the current system culture. This is intentional and prevents an entire class of data conversion errors.

All threads and processes are set to `en-US` culture to ensure consistent, predictable behavior across all environments. Decimal separators, date formats, and number parsing work identically whether running on a Spanish, German, or American system.

This eliminates bugs caused by culture-dependent conversions and makes data exchange reliable.

\
**DateTime is always UTC.** No local times, no timezone conversions, no ambiguity. All dates and times are stored, processed, and transmitted in UTC. This eliminates timezone-related bugs and makes temporal data unambiguous across different geographical locations.

## Preferred Practices

### Don't Use Nullable Types

Avoid nullable types (e.g., `DateTime?`, `decimal?`) unless absolutely necessary. Use default values to represent "empty" states, which provides consistency and eliminates null-checking overhead.

**Default values:**

* Empty DateTime → `DateTime.MinValue`
* Empty decimal → `0`
* Empty Guid → `Guid.Empty`

This approach is semantic: "Maximum 0" clearly means no maximum limit.

***

### Don't Return Anonymous Objects

Never return anonymous objects with `new { ... }` in controllers or services. Anonymous objects are untyped, inconsistent, and break API contracts.

{% tabs %}
{% tab title="Problem" %}

```csharp
// Different types returned in different branches
if (ok)
    return Ok(new { version = "2", revision = "2" });
else
    return Ok(new { version = 2, revision = "2" }); // int vs string
```

{% endtab %}

{% tab title="Second Tab" %}

```csharp
public class AppInfoDTO
{
    public string Version { get; set; } = "";
    public string Revision { get; set; } = "";
    public string Status { get; set; } = "";
}

return Ok(new AppInfoDTO
{
    Version = "2",
    Revision = "2",
    Status = "OK"
});
```

{% endtab %}
{% endtabs %}

***

### Don't Use ! (Negation Operator)

The negation operator reduces clarity, especially in long or nested conditions. Direct checks or explicit comparisons are clearer and more expressive.

```csharp
// Correct
if (user.Enabled == false)
    return;

// Incorrect
if (!user.Enabled)
    return;
```

***

### Collections - Use Extension Methods

Prefer semantic extension methods over verbose null-conditional operators.

```csharp
// Correct
if (_items.IsNotEmpty())
    ProcessItems();

// Incorrect
if (_items?.Count > 0)
    ProcessItems();
```

***

### Guid Comparison

Use semantic extension methods instead of direct comparison with `Guid.Empty`.

```csharp
// Correct
if (f.NextRowId.IsEmpty())
    return;

if (prevId.IsNotEmpty())
    Process(prevId);

// Incorrect
if (f.NextRowId == Guid.Empty)
    return;

if (prevId != Guid.Empty)
    Process(prevId);
```

***

### Use Decimal for Numeric Types

Always use `decimal` for financial and logical operations. Float and double introduce binary rounding errors that cause precision issues.

```csharp
// Correct
decimal price = 19.99m;
decimal total = price * quantity;

// Incorrect
float price = 19.99f;
double total = price * quantity;
```

***

### Extension Methods Reference

#### Type Conversion

* **`.STR()`** - String conversion with better defaults than `.ToString()`

```csharp
// Decimal - always US format (dot as decimal separator)
12.5m.STR()                    // "12.5"
1234.56m.STR()                 // "1234.56"

// Guid - empty guid returns empty string
Guid.Empty.STR()               // ""
Guid.NewGuid().STR()           // "a1b2c3d4-e5f6-..."

// DateTime - ISO format
DateTime.Now.STR()             // "2024-01-15 14:30:00"
DateOnly.Today.STR()           // "2024-01-15"

// Boolean - numeric representation
true.STR()                     // "1"
false.STR()                    // "0"
```

* **`.INT([default])`** - Integer conversion

```csharp
"123".INT()      // 123
"abc".INT()      // Exception
"abc".INT(99)    // 99
```

* **`.DEC([default])`** - Decimal conversion

```csharp
"12.5".DEC()     // 12.5
"abc".DEC()      // Exception
"abc".DEC(9.9m)  // 9.9
```

* **`.BOOL()`** - Boolean conversion

```csharp
"1".BOOL()       // true
"si".BOOL()      // true
"sí".BOOL()      // true
"on".BOOL()      // true
"yes".BOOL()     // true
"true".BOOL()    // true

"0".BOOL()       // false
"false".BOOL()   // false
// Any other value → false
```

***

### Validation

* **`.IsNotNull()`** - Checks if reference is not null
* **`.IsNull()`** - Checks if reference is null
* **`.IsEmpty()`** - Checks if value is empty:
  * `Guid.Empty`
  * `""` (empty string)
  * `DateTime.MinValue`
  * `0` for numeric types
  * Collections with zero elements
* **`.IsNotEmpty()`** - Opposite of `.IsEmpty()`. For collections: returns true if at least one element exists.

These methods include built-in null checks and syntax highlighting.

#### String Comparison

* **`.EqualsIgnoreCase()`** - Case-insensitive string comparison
* **`.LikeM()`** - LIKE-style wildcard pattern matching (case-sensitive)
* **`.LikeMIgnoreCase()`** - LIKE-style wildcard pattern matching (case-insensitive)

#### Dictionary Operations

* **`.GetM(key [, defaultValue])`** - Safe dictionary getter that never throws:

```csharp
MyDictionary.GetM("key")              // null if not found
MyDictionary.GetM("key", "default")   // "default" if not found
```

Use `.GetM()` whenever it reduces lines of code.

## Blazor

### Component Properties

Only use quotes for string literals. Use `@` for expressions to ensure type safety.

```csharp
// Correct
<DataGrid Data=@x.Data />

// Incorrect
<DataGrid Data="x.Data" />
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.dinaup.com/desarrollo/c-code-style-guidelines.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
