All notable changes to the LaunchDarkly Client-Side SDK for .NET will be documented in this file. This project adheres to Semantic Versioning.
5.7.0 (2026-03-13)
5.6.0 (2026-03-03)
5.5.4 (2025-09-29)
5.5.3 (2025-09-25)
5.5.2 (2025-08-26)
5.5.1 (2025-06-24)
5.5.0 (2025-06-02)
- #104 dependency optimisation (#111) (2c7ff62)
- Bump Internal SDK version (#112) (3cb5ae4)
- Update CommonSDK to v7.0.1 (#126) (fad338e)
5.4.0 (2025-05-07)
5.3.0 (2024-10-31)
5.2.1 (2024-06-05)
5.2.0 (2024-05-08)
5.1.0 (2024-03-14)
- Always inline contexts for feature events (c658bee)
- Redact anonymous attributes within feature events (c658bee)
5.0.0 (2024-02-13)
- updating deprecated AndroidClientHandler to AndroidMessageHandler (973b38c)
- updating deprecated AndroidClientHandler to AndroidMessageHandler (#69) (3dc9dba)
- Added Automatic Mobile Environment Attributes functionality which makes it simpler to target your mobile customers based on application name or version, or on device characteristics including manufacturer, model, operating system, locale, and so on. To learn more, read Automatic environment attributes.
Configuration.Builder("myKey").ApplicationInfo(), for configuration of application metadata that may be used in LaunchDarkly analytics or other product features.
When using multi-contexts, then this update can change the FullyQualifiedKey for a given context. This can cause a cache miss in the local cache for a given context, requiring a connection to LaunchDarkly to populate that cache for the new FullyQualifiedKey.
- Fixed an issue with generating the FullyQualifiedKey. The key generation was not sorted by the kind, so the key was not stable depending on the order of the context construction. This affects how flags are locally cached, as they are cached by the FullyQualifiedKey.
- Update to
LaunchDarkly.InternalSdk3.1.1
- (From LaunchDarkly.InternalSdk) Fixed an issue where calling FlushAndWait with TimeSpan.Zero would never complete if there were no events to flush.
The latest version of this SDK supports LaunchDarkly's new custom contexts feature. Contexts are an evolution of a previously-existing concept, "users." Contexts let you create targeting rules for feature flags based on a variety of different information, including attributes pertaining to users, organizations, devices, and more. You can even combine contexts to create "multi-contexts."
For detailed information about this version, please refer to the list below. For information on how to upgrade from the previous version, please read the migration guide.
- In
LaunchDarkly.Sdk, the typesContextandContextKinddefine the new context model. - For all SDK methods that took a
Userparameter, there is now a method that takes aContext. The correspondingUsermethods are defined as extension methods. The SDK still supportsUserfor now, butContextis the preferred model andUsermay be removed in a future version. ConfigurationBuilder.GenerateAnonymousKeysis the new way of enabling the "generate a key for anonymous users" behavior that was previously enabled by setting the user key to null. If you setGenerateAnonymousKeystotrue, all anonymous contexts will have their keys replaced by generated keys; if you do not set it, anonymous contexts will keep whatever placeholder keys you gave them.- The
TestDataflag builder methods have been extended to support now context-related options, such as matching a key for a specific context type other than "user". LdClient.FlushAndWait()andFlushAndWaitAsync()are equivalent toFlush()but will wait for the events to actually be delivered.
- It was previously allowable to set a user key to an empty string. In the new context model, the key is not allowed to be empty. Trying to use an empty key will cause evaluations to fail and return the default value.
- There is no longer such a thing as a
Secondarymeta-attribute that affects percentage rollouts. If you set an attribute with that name in aContext, it will simply be a custom attribute like any other. - The
Anonymousattribute inUseris now a simple boolean, with no distinction between a false state and a null state. - Types such as
IPersistentDataStore, which define the low-level interfaces of LaunchDarkly SDK components and allow implementation of custom components, have been moved out of theInterfacesnamespace into a newSubsystemsnamespace. Application code normally does not refer to these types except possibly to hold a value for a configuration property such asConfigurationBuilder.DataStore, so this change is likely to only affect configuration-related logic.
- Analytics event data now uses a new JSON schema due to differences between the context model and the old user model.
- The SDK no longer adds
deviceandosvalues to the user attributes. Applications that wish to use device/OS information in feature flag rules must explicitly add such information.
- There is no longer a dependency on
LaunchDarkly.JsonStream. This package existed because some platforms did not support theSystem.Text.JsonAPI, but that is no longer the case and the SDK now usesSystem.Text.Jsondirectly for all of its JSON operations. - If you are using the package
LaunchDarkly.CommonSdk.JsonNetfor interoperability with the Json.NET library, you must update this to the latest major version.
- Removed all types, fields, and methods that were deprecated as of the most recent 2.x release.
- Removed the
Secondarymeta-attribute inUserandUserBuilder. - The
Aliasmethod no longer exists because alias events are not needed in the new context model. - The
AutoAliasingOptOutandInlineUsersInEventsoptions no longer exist because they are not relevant in the new context model. LaunchDarkly.Sdk.Json.JsonException: this type is no longer necessary because the SDK now always usesSystem.Text.Json, so any error when deserializing an object from JSON will throw aSystem.Text.Json.JsonException.
- One of the SDK's dependencies,
LaunchDarkly.Logging, had an Authenticode signature without a timestamp. The dependency has been updated to a new version with a valid signature. There are no other changes.
- Analytics events generated by
LdClient.Aliasdid not have correct timestamps, although this was unlikely to affect how LaunchDarkly processed them. - The type
LaunchDarkly.Sdk.UnixMillisecondTimenow serializes and deserializes correctly withSystem.Text.Json.
This is a major rewrite that introduces a cleaner API design, adds new features, and makes the SDK code easier to maintain and extend. See the Xamarin 1.x to client-side .NET 2.0 migration guide for an in-depth look at the changes in 2.0; the following is a summary.
The LaunchDarkly client-side .NET SDK was formerly known as the LaunchDarkly Xamarin SDK. Xamarin for Android and iOS are among its supported platforms, but it can also be used on any platform that supports .NET Core 2+, .NET Standard 2, or .NET 5+. On those platforms, it does not use any Xamarin-specific runtime libraries. To learn more about the distinction between the client-side .NET SDK and the server-side .NET SDK, read: Client-side and server-side SDKs
LdClient.FlagTrackerprovides the ability to get notifications when flag values have changed.LdClient.DataSourceStatusProviderprovides information on the status of the SDK's data source (which normally means the streaming connection to the LaunchDarkly service).LdClient.DoubleVariationandDoubleVariationDetailreturn a numeric flag variation using double-precision floating-point.ConfigurationBuilder.ServiceEndpointsallows you to override the regular service URIs— as you may want to do if you are using the LaunchDarkly Relay Proxy, for instance— in a single place. Previously, the URIs had to be specified individually for each service (StreamingDataSource().BaseURI,SendEvents().BaseURI, etc.).HttpConfigurationBuilder.UseReporttells the SDK to make HTTPREPORTrequests rather thanGETrequests to the LaunchDarkly service endpoints, which may be desirable in rare circumstances but is not available on all platforms.ConfigurationBuilder.PersistenceandPersistenceConfigurationBuilder.MaxCachedUsersallow setting a limit on how many users' flag data can be saved in persistent local storage, or turning off persistence.- The
LaunchDarkly.Sdk.Jsonnamespace provides methods for converting types likeUserandFeatureFlagsStateto and from JSON. - The
LaunchDarkly.Sdk.UserAttributetype provides a less error-prone way to refer to user attribute names in configuration, and can also be used to get an arbitrary attribute from a user. - The
LaunchDarkly.Sdk.UnixMillisecondTimetype provides convenience methods for converting to and from the Unix epoch millisecond time format that LaunchDarkly uses for all timestamp values. - The SDK now periodically sends diagnostic data to LaunchDarkly, describing the version and configuration of the SDK, the architecture and version of the runtime platform, and performance statistics. No credentials, hostnames, or other identifiable values are included. This behavior can be disabled with
ConfigurationBuilder.DiagnosticOptOutor configured withConfigurationBuilder.DiagnosticRecordingInterval.
- .NET Standard 1.6 is no longer supported.
- The SDK no longer has a dependency on
Common.Logging. Instead, it uses a similar but simpler logging facade, theLaunchDarkly.Loggingpackage, which has adapters for various logging destinations. - The SDK no longer has a dependency on the Json.NET library (a.k.a.
Newtonsoft.Json), but instead uses a lightweight custom JSON serializer and deserializer. This removes the potential for dependency version conflicts in applications that use Json.NET for their own purposes, and reduces the number of dependencies in applications that do not use Json.NET. If you do use Json.NET and you want to use it with SDK data types likeUserandLdValue, seeLaunchDarkly.CommonSdk.JsonNet. Those types also serialize/deserialize correctly with theSystem.Text.JsonAPI on platforms where that API is available.
- The base namespace has changed: types that were previously in
LaunchDarkly.Clientare now inLaunchDarkly.Sdk, and types that were previously inLaunchDarkly.Xamarinare now inLaunchDarkly.Sdk.Client. TheLaunchDarkly.Sdknamespace contains types that are not specific to the client-side .NET SDK (that is, they are also used by the server-side .NET SDK):EvaluationDetail,LdValue,User, andUserBuilder. Types that are specific to the client-side .NET SDK, such asConfigurationandLdClient, are inLaunchDarkly.Sdk.Client. UserandConfigurationobjects are now immutable. To specify properties for these classes, you must now useUser.BuilderandConfiguration.Builder.Configuration.Buildernow returns a concrete type rather than an interface.EvaluationDetailis now a struct type rather than a class.EvaluationReasonis now a single struct type rather than a base class with subclasses.EvaluationReasonKindandEvaluationErrorKindconstants now use .Net-style naming (RuleMatch) rather than Java-style naming (RULE_MATCH). Their JSON representations are unchanged.- The
ILdClientinterface is now inLaunchDarkly.Sdk.Client.Interfacesinstead of the main namespace. - The
ILdClientExtensionsmethodsEnumVariation<T>andEnumVariationDetail<T>now have type constraints to enforce thatTreally is anenumtype.
- The default event flush interval is now 30 seconds on mobile platforms, instead of 5 seconds. This is consistent with the other mobile SDKs and is intended to reduce network traffic.
- Logging now uses a simpler, more stable set of logger names instead of using the names of specific implementation classes that are subject to change. General messages are logged under
LaunchDarkly.Sdk, while messages about specific areas of functionality are logged under that name plus.DataSource(streaming, polling, file data, etc.),.DataStore(database integrations),.Evaluation(unexpected errors during flag evaluations), or.Events(analytics event processing).
- All types and methods that were deprecated as of the last 1.x release have been removed.
This is the first release candidate version of the LaunchDarkly client-side .NET SDK 2.0-- a major rewrite that introduces a cleaner API design, adds new features, and makes the SDK code easier to maintain and extend. See the Xamarin 1.x to client-side .NET 2.0 migration guide for an in-depth look at the changes in 2.0; the following is a summary.
The LaunchDarkly client-side .NET SDK was formerly known as the LaunchDarkly Xamarin SDK. Xamarin for Android and iOS are among its supported platforms, but it can also be used on any platform that supports .NET Core 2+, .NET Standard 2, or .NET 5+. On those platforms, it does not use any Xamarin-specific runtime libraries. To learn more about the distinction between the client-side .NET SDK and the server-side .NET SDK, read: Client-side and server-side SDKs
LdClient.FlagTrackerprovides the ability to get notifications when flag values have changed.LdClient.DataSourceStatusProviderprovides information on the status of the SDK's data source (which normally means the streaming connection to the LaunchDarkly service).LdClient.DoubleVariationandDoubleVariationDetailreturn a numeric flag variation using double-precision floating-point.HttpConfigurationBuilder.UseReporttells the SDK to make HTTPREPORTrequests rather thanGETrequests to the LaunchDarkly service endpoints, which may be desirable in rare circumstances but is not available on all platforms.ConfigurationBuilder.PersistenceandPersistenceConfigurationBuilder.MaxCachedUsersallow setting a limit on how many users' flag data can be saved in persistent local storage, or turning off persistence.- The
LaunchDarkly.Sdk.Jsonnamespace provides methods for converting types likeUserandFeatureFlagsStateto and from JSON. - The
LaunchDarkly.Sdk.UserAttributetype provides a less error-prone way to refer to user attribute names in configuration, and can also be used to get an arbitrary attribute from a user. - The
LaunchDarkly.Sdk.UnixMillisecondTimetype provides convenience methods for converting to and from the Unix epoch millisecond time format that LaunchDarkly uses for all timestamp values. - The SDK now periodically sends diagnostic data to LaunchDarkly, describing the version and configuration of the SDK, the architecture and version of the runtime platform, and performance statistics. No credentials, hostnames, or other identifiable values are included. This behavior can be disabled with
ConfigurationBuilder.DiagnosticOptOutor configured withConfigurationBuilder.DiagnosticRecordingInterval.
- .NET Standard 1.6 is no longer supported.
- The SDK no longer has a dependency on
Common.Logging. Instead, it uses a similar but simpler logging facade, theLaunchDarkly.Loggingpackage, which has adapters for various logging destinations. - The SDK no longer has a dependency on the Json.NET library (a.k.a.
Newtonsoft.Json), but instead uses a lightweight custom JSON serializer and deserializer. This removes the potential for dependency version conflicts in applications that use Json.NET for their own purposes, and reduces the number of dependencies in applications that do not use Json.NET. If you do use Json.NET and you want to use it with SDK data types likeUserandLdValue, seeLaunchDarkly.CommonSdk.JsonNet. Those types also serialize/deserialize correctly with theSystem.Text.JsonAPI on platforms where that API is available.
- The base namespace has changed: types that were previously in
LaunchDarkly.Clientare now inLaunchDarkly.Sdk, and types that were previously inLaunchDarkly.Xamarinare now inLaunchDarkly.Sdk.Client. TheLaunchDarkly.Sdknamespace contains types that are not specific to the client-side .NET SDK (that is, they are also used by the server-side .NET SDK):EvaluationDetail,LdValue,User, andUserBuilder. Types that are specific to the client-side .NET SDK, such asConfigurationandLdClient, are inLaunchDarkly.Sdk.Client. UserandConfigurationobjects are now immutable. To specify properties for these classes, you must now useUser.BuilderandConfiguration.Builder.Configuration.Buildernow returns a concrete type rather than an interface.EvaluationDetailis now a struct type rather than a class.EvaluationReasonis now a single struct type rather than a base class with subclasses.EvaluationReasonKindandEvaluationErrorKindconstants now use .Net-style naming (RuleMatch) rather than Java-style naming (RULE_MATCH). Their JSON representations are unchanged.- The
ILdClientinterface is now inLaunchDarkly.Sdk.Client.Interfacesinstead of the main namespace. - The
ILdClientExtensionsmethodsEnumVariation<T>andEnumVariationDetail<T>now have type constraints to enforce thatTreally is anenumtype.
- The default event flush interval is now 30 seconds on mobile platforms, instead of 5 seconds. This is consistent with the other mobile SDKs and is intended to reduce network traffic.
- Logging now uses a simpler, more stable set of logger names instead of using the names of specific implementation classes that are subject to change. General messages are logged under
LaunchDarkly.Sdk.Xamarin.LdClient, while messages about specific areas of functionality are logged under that name plus.DataSource(streaming, polling, file data, etc.),.DataStore(database integrations),.Evaluation(unexpected errors during flag evaluations), or.Events(analytics event processing).
- The SDK was deciding whether to send analytics events based on the
Offlineproperty of the original SDK configuration, rather than whether the SDK is currently in offline mode or not.
- All types and methods that were shown as deprecated/
Obsoletein the last 1.x release have been removed.
- The SDK was failing to get flags in streaming mode when connecting to a LaunchDarkly Relay Proxy instance.
- Removed unnecessary dependencies on
Xamarin.Android.Support.Core.UtilsandXamarin.Android.Support.CustomTabs. (Thanks, Vladimir-Mischenchuk!) - Setting custom base URIs now works correctly even if the base URI includes a path prefix (such as you might use with a reverse proxy that rewrites request URIs). (#26)
- Fixed the base64 encoding of user properties in request URIs to use the URL-safe variant of base64.
- Added
ILdClientextension methodsEnumVariationandEnumVariationDetail, which convert strings to enums. User.Secondary,IUserBuilder.Secondary(replacesSecondaryKey).EvaluationReasonstatic methods and properties for creating reason instances.LdValuehelpers for dealing with array/object values, without having to use an intermediateListorDictionary:BuildArray,BuildObject,Count,Get.LdValue.Parse().
EvaluationReasonproperties all exist on the base class now, so for instance you do not need to cast toRuleMatchto get theRuleIdproperty. This is in preparation for a future API change in whichEvaluationReasonwill become a struct instead of a base class.
- Calling
IdentifyorIdentifyAsyncwith a user that has a null key andAnonymous(true)-- which should generate a unique key for the anonymous user-- did not work. The symptom was that the client would fail to retrieve the flags, and the call would either never complete (forIdentifyAsync) or time out (forIdentify). This has been fixed. - Improved memory usage and performance when processing analytics events: the SDK now encodes event data to JSON directly, instead of creating intermediate objects and serializing them via reflection.
- When parsing arbitrary JSON values, the SDK now always stores them internally as
LdValuerather thanJToken. This means that no additional copying step is required when the application accesses that value, if it is of a complex type. LdValue.Equals()incorrectly returned true for object (dictionary) values that were not equal.- The SDK now specifies a uniquely identifiable request header when sending events to LaunchDarkly to ensure that events are only processed once, even if the SDK sends them two times due to a failed initial attempt.
IUserBuilder.SecondaryKey,User.SecondaryKey.EvaluationReasonsubclasses. Use only the base class properties and methods to ensure compatibility with future versions.
- The JSON serialization of
Userwas producing an extraAnonymousproperty in addition toanonymous. If Newtonsoft.Json was configured globally to force all properties to lowercase, this would cause an exception when serializing a user since the two properties would end up with the same name. (#22)
- Added support for upcoming LaunchDarkly experimentation features. See
ILdClient.Track(string, LdValue, double). User.AnonymousOptionalandIUserBuilder.AnonymousOptionalallow treating theAnonymousproperty as nullable (necessary for consistency with other SDKs). See note about this under Fixed.- Added
LaunchDarkly.Logging.ConsoleAdapteras a convenience for quickly enabling console logging; this is equivalent toCommon.Logging.Simple.ConsoleOutLoggerFactoryAdapter, but the latter is not available on some platforms.
Configuration.Builderwas not setting a default value for theBackgroundPollingIntervalproperty. As a result, if you did not set the property explicitly, the SDK would throw an error when the application went into the background on mobile platforms.IUserBuilderwas incorrectly setting the user'sAnonymousproperty tonulleven if it had been explicitly set tofalse. Null and false behave the same in terms of LaunchDarkly's user indexing behavior, but currently it is possible to create a feature flag rule that treats them differently. SoIUserBuilder.Anonymous(false)now correctly sets it tofalse, just as the deprecated methodUserExtensions.WithAnonymous(false)would.LdValue.Convert.Longwas mistakenly converting to anintrather than along. (CommonSdk #32)
First GA release.
For release notes on earlier beta versions, see the beta changelog.