はじめに
現在のUnityで利用できるC#のバージョンはC#9
までになってます。ただ少し裏技?を使うことで実質C#11
まで利用することが可能になっています。
ただ注意点としてはasmdef
が絡んでくるとよく知られているCsprojModifier
を用いる手法だけだといけなかったはずです。(CsprojModifierでやっていることはAssetPostprocessor.OnGeneratedCSProject
を用いてcsproj
に変更を加える)
本題のCallerArgumentExpression
なのですが、C#10から登場した属性です。Unityに対してCsprojModifier
などを用いてC#のバージョンをあげたとしても、定義がないと怒られてしまいます。
やり方
以下を自前で定義してあげればOKです。
namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] public sealed class CallerArgumentExpressionAttribute : Attribute { public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } public string ParameterName { get; } } }
実験
using System.Runtime.CompilerServices; using UnityEngine; public class Sample : MonoBehaviour { private void Start() { Hoge("テキスト"); } private static void Hoge(string text, [CallerArgumentExpression("text")] string? textExpression = null) { // テキスト Debug.Log(text); // "テキスト" Debug.Log(textExpression); } }
ちなみに
CallerArgumentExpression
を主に取り上げましたが、required
修飾子やinit
アクセサを利用したい場合も同様に定義を自分でしてあげる必要があります。
// 以下のように required を利用したい, initを利用したい場合は public class Person { public required string Name { get; init; } public int? Age { get; init; } }
requiredを利用するために
namespace System.Runtime.CompilerServices { /// <summary> /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied. /// </summary> [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] public sealed class CompilerFeatureRequiredAttribute : Attribute { public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } /// <summary> /// The name of the compiler feature. /// </summary> public string FeatureName { get; } /// <summary> /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand <see cref="FeatureName"/>. /// </summary> public bool IsOptional { get; init; } /// <summary> /// The <see cref="FeatureName"/> used for the ref structs C# feature. /// </summary> public const string RefStructs = nameof(RefStructs); /// <summary> /// The <see cref="FeatureName"/> used for the required members C# feature. /// </summary> public const string RequiredMembers = nameof(RequiredMembers); } }
using System.ComponentModel; namespace System.Runtime.CompilerServices { /// <summary>Specifies that a type has required members or that a member is required.</summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] [EditorBrowsable(EditorBrowsableState.Never)] public sealed class RequiredMemberAttribute : Attribute { } }
initを利用するために
namespace System.Runtime.CompilerServices { internal sealed class IsExternalInit { } }
runtime/src/tasks/Common/IsExternalInit.cs at main · dotnet/runtime · GitHub