C++, Go, Java, Rust, JavaScript and TypeScript
The delivery rule is an entry point. For a more substantial comparison, inspect branching priority, fresh defaults and concurrency ownership across the languages. See readability under real business rules for policy branches, initialization and coordination.
What does the same business rule ask a reader to understand in each language? This page uses a small delivery calculation, then compares the surrounding application models. The examples use ordinary idioms in each language: exceptions where customary, and returned errors in Go and Rust.
For .NET-to-.NET comparisons, see C# and VB.NET. For a calculation involving decimal money and rounding, see pricing an order.
One rule, the same boundaries
An order total of at least 100 receives free delivery. A smaller nonnegative total costs 5. A negative total fails. All amounts here are whole currency units represented as signed 32-bit integers. There is no fractional money, tax, currency conversion, I/O or concurrency in this calculation.
| Order total | Result |
|---|---|
| 0 | 5; zero is a valid total |
| 99 | 5 |
| 100 | 0; the boundary is inclusive |
| 101 | 0 |
| 2,147,483,647 | 0; the largest signed 32-bit input |
| -1 or -2,147,483,648 | Argument failure |
Typed hosts must validate decoded input before calling the calculation. A function signature is not a JSON validator. JavaScript and TypeScript include an explicit integer/range guard because their number type also represents fractional and nonfinite values. The examples do not equate an exception with a returned error: the business failure is the same, while its representation differs.
DirectSharp
// Delivery policy: reject a negative amount before choosing the fee.
public class DeliveryRule
static action Calculate(orderTotal as Integer)
returns Integer
require orderTotal >= 0 otherwise new Global.System.ArgumentOutOfRangeException("orderTotal")
if orderTotal >= 100 then
return 0
end if
return 5
end action
end class
The parameter type establishes the integer contract. require names the precondition, and otherwise selects an ordinary .NET exception. end if and end action tell the reader which construct ends.
A rose is a Rose is a ROSE in DirectSharp. All six languages below distinguish those identifiers. This changes name lookup, rather than turning stored strings or passwords into case-insensitive data. Explicit arguments.name and self.Name resolve parameter/member ambiguity when needed.
C++
// Delivery policy: reject a negative amount before choosing the fee.
#include <cstdint>
#include <stdexcept>
std::int32_t calculate(std::int32_t order_total)
{
if (order_total < 0) {
throw std::out_of_range("order_total must be nonnegative");
}
if (order_total >= 100) {
return 0;
}
return 5;
}
The rule itself is short in C++ too. Braces mark its blocks, and std::out_of_range carries the failure. std::int32_t makes the chosen representation explicit on platforms providing that exact-width type. C++ permits implicit numeric conversions at call sites, so an application must also control narrowing conversions at its input boundary.
C++ gives applications control over value layout, allocation, destruction and native integration. RAII ties cleanup to object lifetimes, including unwinding; ownership is expressed through values, smart pointers and library contracts. Templates, reference categories and lifetime reasoning become relevant as the application grows. DirectSharp uses managed .NET objects and its specified resource scopes; its readable source does not offer C++'s native-memory model.
Choose C++ when native libraries, hardware interfaces or precise layout/lifetime control drive the application. DirectSharp's focus is ordinary .NET application code that benefits from existing managed libraries and explicit business rules.
Go
// Delivery policy: reject a negative amount before choosing the fee.
package deliveryquote
import "errors"
func Calculate(orderTotal int32) (int32, error) {
if orderTotal < 0 {
return 0, errors.New("orderTotal must be nonnegative")
}
if orderTotal >= 100 {
return 0, nil
}
return 5, nil
}
Go returns the failure alongside the result. The caller checks err before using the fee; the zero accompanying an error is not a successful free-delivery decision. This expected argument error does not use panic as a substitute for normal error handling.
Go has static types, garbage collection, structs, methods and implicitly satisfied interfaces. It does not use DirectSharp's class inheritance model. Exported names start with an uppercase letter, so changing a name's capitalization can also affect package visibility. That convention has no equivalent in DirectSharp's case-insensitive lookup.
Goroutines and channels are useful for services and pipelines, but a goroutine does not automatically become owned work that its parent joins. Applications establish completion, error propagation and cancellation, often through contexts and coordination libraries. defer schedules a call for function return; it is not itself a lexical resource block. DirectSharp's designed concurrent scopes and resource scopes have their own explicit lifetime rules. The async comparison explains why matching successful outputs alone does not establish equivalent failure behavior.
Java
public final class DeliveryRule {
public static int calculate(int orderTotal) {
if (orderTotal < 0) {
throw new IllegalArgumentException("orderTotal must be nonnegative");
}
if (orderTotal >= 100) {
return 0;
}
return 5;
}
}
Java's class, static method and primitive int will be familiar to many .NET developers. This argument failure uses an unchecked exception, so the method does not need a throws declaration. Other Java APIs use checked exceptions and declare those contracts explicitly.
Both Java and DirectSharp support ordinary object-oriented application development with managed memory and established libraries. Java runs on the JVM and uses its ecosystem; DirectSharp targets .NET and its CLR APIs. A JVM library is not made directly callable merely by translating its Java syntax into DirectSharp. Integration across runtimes needs a service boundary, bridge or other deliberate arrangement.
Java's try-with-resources uses AutoCloseable. Its primary/suppressed-exception rules differ from ordinary .NET disposal unwinding. Preserve the actual cleanup-failure policy when translating resource code. Java also has a mature collection of concurrency choices, including executors, futures and virtual threads; none makes an arbitrary translated workflow equivalent to DirectSharp's specified all, first or any scope.
Rust
// Delivery policy: reject a negative amount before choosing the fee.
#[derive(Debug, PartialEq, Eq)]
pub enum QuoteError {
NegativeTotal,
}
pub fn calculate(order_total: i32) -> Result<i32, QuoteError> {
if order_total < 0 {
return Err(QuoteError::NegativeTotal);
}
if order_total >= 100 {
return Ok(0);
}
Ok(5)
}
Rust makes the possible business failure part of Result. Callers can match it or propagate it with ? in a compatible function. A negative total is an expected error, not a reason to replace the function with a panic. The final expression supplies the successful value.
Rust's ownership and borrowing rules address memory and aliasing before execution. Traits and explicit enum variants offer different ways to organize an application from DirectSharp's normal .NET classes and interfaces. DirectSharp's readonly bindings and resource scopes do not provide Rust's borrow-checking guarantees.
Rust futures run through an executor/runtime selected by the application. Dropping a future is not a general promise that all external effects have been undone or that independently spawned work has been joined. Keep cancellation, task ownership and cleanup policy explicit when comparing it with DirectSharp's concurrency design. Rust is especially relevant when native deployment and memory/lifetime guarantees are requirements; DirectSharp prioritizes readable managed application logic and ordinary .NET library use.
JavaScript
// Delivery policy: reject a negative amount before choosing the fee.
export function calculate(orderTotal) {
if (!Number.isInteger(orderTotal) ||
orderTotal < -2147483648 || orderTotal > 2147483647) {
throw new TypeError("orderTotal must be a signed 32-bit integer");
}
if (orderTotal < 0) {
throw new RangeError("orderTotal must be nonnegative");
}
if (orderTotal >= 100) {
return 0;
}
return 5;
}
The guard deliberately rejects "100", null, undefined, Boolean values, fractions, NaN and infinities instead of relying on coercion. Every signed 32-bit integer is represented exactly by JavaScript's number. Extending this example to decimal money would require a deliberate numeric representation and rounding policy; the number type alone does not supply .NET Decimal semantics.
JavaScript is dynamically typed and serves browser applications, server hosts and other embedded runtimes. Modules, closures and functions are natural application building blocks. DirectSharp resolves types and names before execution and targets .NET rather than emitting JavaScript for a browser.
async functions return promises. await observes their completion, while cancellation depends on the API, often through an AbortSignal. Promise.all rejects when an input rejects, but does not itself cancel the remaining operations or wait for every remaining operation to settle before reporting that rejection. It is therefore insufficient as a direct implementation of an owned DirectSharp all scope. Resource ownership likewise needs the host/library's disposal contract and appropriate cleanup, rather than an assumption that garbage collection closes a file or connection.
TypeScript
// Delivery policy: reject a negative amount before choosing the fee.
export function calculate(orderTotal: number): number {
if (!Number.isInteger(orderTotal) ||
orderTotal < -2147483648 || orderTotal > 2147483647) {
throw new TypeError("orderTotal must be a signed 32-bit integer");
}
if (orderTotal < 0) {
throw new RangeError("orderTotal must be nonnegative");
}
if (orderTotal >= 100) {
return 0;
}
return 5;
}
TypeScript gives JavaScript callers a static contract. Its number still includes fractional and nonfinite values, so even a type-checked caller can supply a value the application rule rejects. The guard remains necessary. Type annotations and interfaces are normally erased; they do not validate JSON or stop untyped JavaScript from calling the emitted function. A type assertion changes what the checker believes, not the received value.
TypeScript uses JavaScript's runtime, promises and host APIs. Its structural types and discriminated unions are useful for application contracts, but do not create CLR classes or .NET interfaces. DirectSharp uses CLR type identities and can bind ordinary .NET generic APIs, delegates and expression trees. A TypeScript interface used in a frontend and a DirectSharp interface used in a service need a shared wire contract or generated bindings to communicate.
For a browser frontend, TypeScript can be the natural companion to a DirectSharp/.NET service. This is a choice of application boundaries and deployment targets, rather than an argument that one source syntax should run everywhere.
What the comparison establishes
Every version exposes the same inclusive threshold and handles the negative-total failure. The returned-error versions make the caller handle a different shape of result; the exception versions use their runtime's exception machinery. Whole-program error handling must preserve that distinction.
| Concern | DirectSharp choice | What to inspect when translating |
|---|---|---|
| Names | Case-insensitive identity with explicit qualification | Case-only distinctions; Go exported-name visibility |
| Business inputs | Static parameter types plus explicit contracts | Native narrowing, untrusted JSON, integer versus floating-point representations |
| Objects | Ordinary CLR classes and interfaces | C++/Rust ownership, Go interfaces, Java/JVM types, JavaScript prototypes and TypeScript structural types |
| Failure | Contracts and .NET exceptions | Exceptions versus Go errors or Rust Result; caller handling |
| Resources | Defined lexical ownership and disposal contracts | RAII/Drop, function-level defer, AutoCloseable and host-specific disposal |
| Concurrency | Explicit await intent and designed owned scopes | Child lifetime, cancellation cooperation, failure reporting and loser settlement |
| Libraries | Direct .NET interoperability | The native ecosystem or an explicit cross-runtime boundary |
Readable words and named endings are DirectSharp's design choice. C++, Go, Java, Rust, JavaScript and TypeScript each have readable idioms and established uses. The useful adoption question is whether DirectSharp helps a particular team understand and maintain its .NET application rules. Source length is not evidence of performance, safety or toolchain maturity.
All comparisons · Why DirectSharp · Executable first steps
For API, domain, data/AI and worker architecture choices, see choosing by workload, with direct links to the C# and Python application comparisons.