Design and maintain explicit F# and C# boundaries in mixed .NET solutions, including project references, public API shape, async/task interop, nullability, options, records, and package-facing contracts.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add gaelic-ghost/socket --skill fsharp-csharp-interop --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Fsharp Csharp Interop?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/gaelic-ghost-fsharp-csharp-interop)More formats (shields.io, HTML) on the badges page.
---
name: fsharp-csharp-interop
description: Design and maintain explicit F# and C# boundaries in mixed .NET solutions, including project references, public API shape, async/task interop, nullability, options, records, and package-facing contracts.
license: Apache-2.0
compatibility: Designed for Codex and compatible Agent Skills clients working with mixed F# and C# .NET solutions.
metadata:
owner: gaelic-ghost
repo: socket
category: dotnet-interop
allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*)
---
# F# And C# Interop
## Purpose
Keep mixed F# and C# solutions intentional.
The practical job is to decide which language owns which responsibility, make the project-reference direction explicit, and shape public APIs so each language can call the other without awkward translation code leaking everywhere.
## When To Use
- Use this skill when a solution contains both `.fsproj` and `.csproj` projects.
- Use this skill when adding an F# library to a C# app or service.
- Use this skill when adding a C# host or infrastructure project around F# domain code.
- Use this skill when public package APIs need to work well from both F# and C#.
## Source Check
Use repo-local .NET files, checked-out dependency sources, Dash MCP or Dash HTTP for installed .NET docsets, and then official Microsoft documentation when Dash/local coverage is missing or stale:
- [F# documentation](https://learn.microsoft.com/dotnet/fsharp/)
- [C# documentation](https://learn.microsoft.com/dotnet/csharp/)
- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/)
- [`dotnet add reference` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-add-reference)
## Boundary Workflow
1. Inspect project graph:
```bash
rg --files -g '*.fsproj' -g '*.csproj' -g '*.sln' -g '*.slnx'
```
2. Identify the language-owned responsibilities:
- F# domain library
- C# host app
- C# ASP.NET Core service
- F# CLI
- shared abstractions
- tests
3. Choose dependency direction.
4. Shape the API at the boundary.
5. Add tests from the consuming side when the boundary is public or fragile.
6. Run solution-level build and tests.
## Good Mixed Shapes
Common durable shapes:
- F# domain library consumed by a C# app or ASP.NET Core host
- F# transformation package consumed by C# tools
- C# infrastructure adapter consumed by an F# application
- shared test projects that verify public package behavior from both languages
Avoid mixed language solutions when the only reason is indecision. Ask for a language choice instead.
## API Boundary Notes
When C# consumes F#:
- be careful with options, tuples, curried functions, and discriminated unions
- expose C#-friendly functions or classes only at the boundary that needs them
- keep the idiomatic F# API intact when F# callers still matter
When F# consumes C#:
- handle nullability explicitly
- wrap exception-heavy APIs into clearer result shapes when useful
- keep async/task conversion visible at the edge
## Project References
Use `dotnet add reference` or direct project-file edits that match the repo style.
After reference changes, run:
```bash
dotnet build
dotnet test
```
Use package references instead of project references only when the dependency is intentionally versioned and released independently.
## Output Shape
Return:
1. `Boundary`: which language owns which project.
2. `Dependency direction`: project references and rationale.
3. `API shape`: F#-native, C#-friendly, or dual surface.
4. `Interop risks`: nullability, options, unions, async/task, file ordering.
5. `Validation`: exact build and test commands.
## Guardrails
- Do not add mixed language projects without naming the concrete benefit.
- Do not flatten F# domain modeling into C#-shaped classes just for convenience.
- Do not expose awkward F# internals to C# consumers when a small boundary API would be clearer.
- Do not hide nullability or task conversion problems.
- Do not change dependency direction casually in an existing solution.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!