100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Platform-Specific Code

Learn how to branch behavior per platform in .NET MAUI using conditional compilation, partial classes, and platform folders.

Navigation & PlatformIntermediate10 min readJul 10, 2026
Analogies

Why Platform-Specific Code Is Necessary

Even though .NET MAUI provides a shared abstraction over UI and device APIs, some behavior genuinely differs per operating system — status bar color on iOS, edge-to-edge display on Android, or window sizing on Windows — and the shared C# code has no cross-platform API for it. MAUI's single-project structure keeps this platform code organized under Platforms/Android, Platforms/iOS, Platforms/MacCatalyst, and Platforms/Windows folders, each compiled only into the corresponding target.

🏏

Cricket analogy: This is like the same laws of cricket applying everywhere, but pitch preparation genuinely differing between a green seamer at Headingley and a dry turner in Chennai — the shared rulebook still needs local adjustments.

Conditional Compilation with MSBuild Constants

The MAUI SDK defines preprocessor symbols like ANDROID, IOS, MACCATALYST, and WINDOWS automatically based on the current target framework being built, so you can wrap platform-only code in #if blocks directly inside otherwise-shared files. This is the lightest-weight approach for a few lines of divergence, but it makes files harder to read as branches accumulate, so larger platform differences are usually better handled with partial classes split across the Platforms folders instead.

🏏

Cricket analogy: This is like a single scorecard template with a small conditional note — 'DRS available' — inserted only for internationals, while keeping the same base template for domestic matches without it.

csharp
public void ConfigureStatusBar()
{
#if ANDROID
    var window = Platform.CurrentActivity?.Window;
    window?.SetStatusBarColor(Android.Graphics.Color.ParseColor("#1E88E5"));
#elif IOS
    UIKit.UIApplication.SharedApplication.StatusBarStyle =
        UIKit.UIStatusBarStyle.LightContent;
#endif
}

Partial Classes and Platforms Folders

For larger divergence, declare a partial class with a shared method signature in cross-platform code, then implement it once per platform in Platforms/Android/DeviceHelper.cs, Platforms/iOS/DeviceHelper.cs, and so on — each platform folder is only compiled into its matching target, so there's no #if needed and each file can freely use platform SDK types like Android.Content.Context or UIKit.UIViewController. The shared caller just invokes the partial method as an ordinary API, unaware of which platform implementation will run.

🏏

Cricket analogy: This is like a national cricket board publishing one shared fixture format but letting each host venue's ground staff independently prepare the pitch to local conditions without needing sign-off from the other venues.

csharp
// Shared: Platforms-agnostic partial declaration
public partial class DeviceHelper
{
    public static partial string GetPlatformVersion();
}

// Platforms/Android/DeviceHelper.cs
public partial class DeviceHelper
{
    public static partial string GetPlatformVersion() =>
        $"Android {Android.OS.Build.VERSION.Release}";
}

// Platforms/iOS/DeviceHelper.cs
public partial class DeviceHelper
{
    public static partial string GetPlatformVersion() =>
        $"iOS {UIKit.UIDevice.CurrentDevice.SystemVersion}";
}

DeviceInfo.Platform (from Microsoft.Maui.Devices) gives you a cross-platform enum check — DeviceInfo.Platform == DevicePlatform.Android — for simple runtime branching that doesn't require conditional compilation or separate files at all.

Code inside a Platforms/iOS file will not compile when building for Android, and vice versa — referencing a type like UIKit.UIViewController outside its matching platform folder (without an #if guard) breaks the build for every other target, not just the one you're testing on.

  • Platform folders (Platforms/Android, Platforms/iOS, Platforms/MacCatalyst, Platforms/Windows) compile only into their matching target.
  • MSBuild defines ANDROID, IOS, MACCATALYST, WINDOWS symbols usable in #if blocks for small divergences.
  • Partial classes/methods let each platform folder implement a shared API independently without #if clutter.
  • DeviceInfo.Platform gives simple runtime branching without conditional compilation for lightweight checks.
  • Platform SDK types (UIKit, Android.*) are only valid inside their own platform folder or guarded #if block.
  • Prefer partial classes over heavy #if nesting once platform divergence grows beyond a few lines.
  • Referencing a platform type outside its guard breaks compilation for every other target, not just the current one.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#NETMAUIStudyNotes#PlatformSpecificCode#Platform#Specific#Code#Necessary#StudyNotes#SkillVeris#ExamPrep