> ## Content Index
> Fetch the complete content index at: https://blogs.remobjects.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# #ifdef, redefined
- URL: https://blogs.remobjects.com/2017/12/21/ifdef-redefined/
- Published: 2017-12-21T18:49:19.000Z
- Updated: 2018-08-22T06:17:38.000Z
- Author: marc hoffman
- Tags: #Import 2026-08-17 20:17

Using `#ifdef`s, or your language's equivalent, is a common occurrence in code, not only when writing cross-platform code. `#ifdef`s (or `#if` in C#, Swift and Iodine and `{$IF}` in Oxygene), let you *conditionally* compile different parts of your project — for example to account for APIs not available on all platforms, or for code you want to run only in debug or in release mode.

The downside is, `#ifdef`s make for pretty *ugly* code:

```csharp
#if COCOA
var formatter = new Foundation.NSDateFormatter();
formatter.dateFormat = format;
formatter.timeZone = timeZone;
return formatter.dateFromString(value);
#endif
#if JAVA
var formatter = new java.text.SimpleDateFormat(format, Locale.Invariant);
formatter.TimeZone = timeZone;
return DateTime(formatter.parse(value));
#endif

```

Elements 10 does away with the need for ugly `#ifdef` syntax by introducing a new `defined()` system function. With `defined()`, you can express conditional compilation as part of regular code flow – the compiler will take care of the rest.

```csharp
if (defined("COCOA")) {
  var formatter = new Foundation.NSDateFormatter();
  formatter.dateFormat = format;
  formatter.timeZone = timeZone;
  return formatter.dateFromString(value);
} else if (defined("JAVA")) {
  var formatter = new java.text.SimpleDateFormat(format, Locale.Invariant);
  formatter.TimeZone = timeZone;
  return DateTime(formatter.parse(value));
}

```

That's already much nicer, right? Notice how this now flows just like regular conditional code would. But also notice how you can *still* use platform-specifc APIs in each section of code! That's because the compiler still takes this `if` clause apart, and will compile one part when targeting Cocoa, and the other when targeting Java.

The same of course works in all languages. E.g. Oxgyene:

```oxygene
if defined('COCOA') then begin
  var lFormatter := new Foundation.NSDateFormatter();
  lFormatter.dateFormat := aFormat;
  lFormatter.timeZone := timeZone;
  result := lFormatter.dateFromString(value);
end
else if defined('JAVA') then begin
  var lFormatter := new java.text.SimpleDateFormat(aFormat, Locale.Invariant);
  lFormatter.TimeZone =: timeZone;
  result := lFormatter.parse(value) as DateTime;
end;

```

But we can take this a step further:

```csharp
public string getPathSeparator() {
  if (defined("COCOA") || Environment.OS == OperatingSystem.macOS) {
    return "/";
  } else if Environment.OS == OperatingSystem.Windows {
    return "\";
  }
}

```

In this (a bit contrived – but I have code *like* this all across our EBuild project) example, we're combining `defined` with *regular* application logic.

When building for Cocoa, the compiler will determine `defined("COCOA")` to be true, short-circuit the rest of the `if` clause, and simply emit the `return "/"`. No runtime check happening at all.

When building for a different platform, it will emit code for the platform check, and the right path will be taken at runtime.

This allows for some *pretty* powerful and flexible cross-platform code that's also a lot easier to read than the `#ifdef` equivalent.

But it's not only cross-platform code that can benefit; consider for example the following:

```csharp
var report = ...;
if (defined("DEBUG") || report.level == ReportLevel.critcal) {
  report.emailToCEO()
}

```

Here, how to react to a given "report" object depends *both* on the debug/release level of the app, but *also* on runtime logic. In debug builds, all reports will be sent, while in release builds the `level` will be taken into consideration at runtime.

## Swift and #defined

While `defined()` is a system function provided by the Elements compiler and available on all languages and platforms, we've also added a second syntax specifically for Swift that is more aligned with existing `#available()` and similar constructs:

So in Swift, regardless of platform, you can use `#defined()` and omit the quotes, e.g.:

```swift
if #defined(COCOA) && #available(iOS 11.2) {
  ...
}

```

This works the same as `defined("COCOA")` would, just looks more Swifty.

## #if Isn't Going Away

Of course `#if` and `{$IF}` continue to be supported as well, and still have their place when conditionally defining larger scopes than an `if` statement can handle – such as whole methods or classes.

But you will find that inside method bodies, the new syntax allows for much more expressive and easier to read conditional compilation – not to mention better integration of compile-time conditions with runtime decisions, as seen in the samples above.

The new `defined()` infrastructure is just one of many, *many* new features for Elements 10 already available in the current builds. Check it out and let us know what you think!