Numatytasis programos ekvivalentas (tipas)

Aš naudoju atspindį, kad kartotumėte Type ypatybes ir nustatytumėte tam tikrus tipus pagal nutylėjimą. Dabar aš galiu aiškiai įvesti tipo jungiklį ir nustatyti default(Type) , bet norėčiau tai padaryti vienoje eilutėje. Ar yra numatytasis programinės įrangos ekvivalentas?

460
28 нояб. nustatyti į tagus2k 28 nov. 2008-11-28 13:11 '08, 13.11 val. 2008-11-28 13:11
@ 13 atsakymų
  • Vertės tipo atveju naudokite „ Activator.CreateInstance“ ir ji turėtų veikti gerai.
  • Naudojant atskaitos tipą, tiesiog grąžinkite nulį.
 public static object GetDefault(Type type) { if(type.IsValueType) { return Activator.CreateInstance(type); } return null; } 

Naujesnėje .net versijoje, pvz., type.IsValueType standarte, type.IsValueType turėtų būti parašyta kaip type.GetTypeInfo().IsValueType

620
09 дек. atsakymas duotas Dror Helper 09 dec. 2008-12-09 18:14 '08, 18:14 pm 2008-12-09 18:14

Kodėl neturite skambinti metodu, kuris grąžina numatytąją vertę (T) su refleksija? Galite naudoti bet kurį „GetDefault“ tipą naudodami:

  public object GetDefault(Type t) { return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null); } public T GetDefaultGeneric<T>() { return default(T); } 
94
05 нояб. atsakymas duotas drake7707 05 lapkričio. 2011-11-05 22:24 '11, 10:24 val. 2011-11-05 22:24

Galite naudoti PropertyInfo.SetValue(obj, null) . Jei paskambinsite į vertės tipą, jis suteiks numatytąją vertę. Šis elgesys dokumentuojamas .NET 4.0 ir .NET 4.5 .

78
24 апр. JoelFan paskelbė balandžio 24 d 2012-04-24 00:48 '12 12:48 AM 2012-04-24 00:48

Jei naudojate .NET 4.0 ar naujesnę versiją ir norite programinės įrangos versijos, kuri nėra kodų kodavimo kodas, galite sukurti Expression , kompiliuoti ir paleisti jį skrydžio metu.

Tolesnis išplėtimo metodas bus Type ir gaus vertę, grąžintą iš default(T) naudojant „ Default metodą „ Expression klasėje:

 public static T GetDefaultValue<T>() { // We want an Func<T> which returns the default. // Create that expression here. Expression<Func<T>> e = Expression.Lambda<Func<T>>( // The default value, always get what the *code* tells us. Expression.Default(typeof(T)) ); // Compile and return the value. return e.Compile()(); } public static object GetDefaultValue(this Type type) { // Validate parameters. if (type == null) throw new ArgumentNullException("type"); // We want an Func<object> which returns the default. // Create that expression here. Expression<Func<object>> e = Expression.Lambda<Func<object>>( // Have to convert to object. Expression.Convert( // The default value, always get what the *code* tells us. Expression.Default(type), typeof(object) ) ); // Compile and return the value. return e.Compile()(); } 

Taip pat turėtumėte išsaugoti aukščiau nurodytą vertę pagal Type , tačiau reikia nepamiršti, kad jei jį skambinsite daugeliu Type atvejų ir nenaudojate jos visą laiką, talpyklos suvartota atmintis gali būti didesnė už naudą.

54
04 окт. atsakymas, kurį pateikė casperOne 04 okt. 2012-10-04 21:24 '12 21:24 2012-10-04 21:24

Kodėl jūs sakote, kad generiniai vaistai nėra matomi?

  public static object GetDefault(Type t) { Func<object> f = GetDefault<object>; return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null); } private static T GetDefault<T>() { return default(T); } 
37
26 окт. Rob Fonseca-Ensor atsakymas, pateiktas spalio 26 d. 2010-10-26 23:47 '10, 23:47, 2010-10-26 23:47

Tai optimizuotas „Flem“ sprendimas:

 using System.Collections.Concurrent; namespace System { public static class TypeExtension { //a thread-safe way to hold default instances created at run-time private static ConcurrentDictionary<Type, object> typeDefaults = new ConcurrentDictionary<Type, object>(); public static object GetDefaultValue(this Type type) { return type.IsValueType ? typeDefaults.GetOrAdd(type, Activator.CreateInstance) : null; } } } 
22
14 нояб. Atsakymas pateikiamas 14 d. 2012-11-14 13:00 '12 13:00 val. 2012-11-14 13:00

Pasirinktas atsakymas yra geras atsakymas, bet būkite atsargūs su grąžinamu objektu.

 string test = null; string test2 = ""; if (test is string) Console.WriteLine("This will never be hit."); if (test2 is string) Console.WriteLine("Always hit."); 

Ekstrapoliavimas ...

 string test = GetDefault(typeof(string)); if (test is string) Console.WriteLine("This will never be hit."); 
7
16 окт. BSick7 atsakoma spalio 16 d. 2010-10-16 22:30 '10 10:30 val. 2010-10-16 22:30

Išraiškos gali padėti čia:

  private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>(); private object GetTypedNull(Type type) { Delegate func; if (!lambdasMap.TryGetValue(type, out func)) { var body = Expression.Default(type); var lambda = Expression.Lambda(body); func = lambda.Compile(); lambdasMap[type] = func; } return func.DynamicInvoke(); } 

Nenagrinėjau šio fragmento, bet manau, kad jis turėtų gaminti „tipinius“ nulius referenciniams tipams.

5
26 дек. Konstantino Isaevo atsakymas gruodžio 26 d 2011-12-26 03:15 '12 at 3:15 2011-12-26 03:15

Aš atlieku tą pačią užduotį kaip ir šis.

 //in MessageHeader private void SetValuesDefault() { MessageHeader header = this; Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this); } //in ObjectPropertyHelper public static void SetPropertiesToDefault<T>(T obj) { Type objectType = typeof(T); System.Reflection.PropertyInfo [] props = objectType.GetProperties(); foreach (System.Reflection.PropertyInfo property in props) { if (property.CanWrite) { string propertyName = property.Name; Type propertyType = property.PropertyType; object value = TypeHelper.DefaultForType(propertyType); property.SetValue(obj, value, null); } } } //in TypeHelper public static object DefaultForType(Type targetType) { return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; } 
3
28 нояб. Atsakymą pateikia kpollock lapkričio 28 d 2008-11-28 14:18 '08, 14:18, 2008-11-28 14:18

Iki šiol nėra nieko paprasto ir elegantiško, bet turiu vieną idėją: jei žinote, kokio tipo turtą norite nustatyti, galite parašyti savo default(T) . Yra du atvejai: T yra vertės tipas, o T - atskaitos tipas. Tai galite pamatyti nustatę T.IsValueType . Jei T yra atskaitos tipas, galite tiesiog jį nustatyti null . Jei T yra vertės tipas, tada jis turės ne parametro konstruktorių, kurį galite skambinti, kad gautumėte „tuščią“ vertę.

3
28 нояб. atsakymas duotas Vilx- 28 lapkričio. 2008-11-28 13:30 '08, 13:30, 2008-11-28 13:30

Lygiavertis „Dror“ atsakas, bet kaip pratęsimo metodas:

 namespace System { public static class TypeExtensions { public static object Default(this Type type) { object output = null; if (type.IsValueType) { output = Activator.CreateInstance(type); } return output; } } } 
2
26 июня '12 в 18:48 2012-06-26 18:48 atsakymą Paulius Flemingas pateikė birželio 26 d. 12 val. 18:48 2012-06-26 18:48
  /// <summary> /// returns the default value of a specified type /// </summary> /// <param name="type"></param> public static object GetDefault(this Type type) { return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null; } 
0
31 марта '14 в 21:52 2014-03-31 21:52 atsakymą pateikė Kaz-LA kovo 31 d. 14 d. 21:52 2014-03-31 21:52

Nedideli pakeitimai @Rob Fonseca-Ensor sprendime : Šis išplėtimo metodas taip pat veikia .Net Standard, nes naudoju GetRuntimeMethod, o ne GetMethod.

 public static class TypeExtensions { public static object GetDefault(this Type t) { var defaultValue = typeof(TypeExtensions) .GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { }) .MakeGenericMethod(t).Invoke(null, null); return defaultValue; } public static T GetDefaultGeneric<T>() { return default(T); } } 

... ir tinkamas vieneto testas tiems, kurie rūpinasi kokybe:

 [Fact] public void GetDefaultTest() { // Arrange var type = typeof(DateTime); // Act var defaultValue = type.GetDefault(); // Assert defaultValue.Should().Be(default(DateTime)); } 
0
10 янв. atsakymas, kurį pateikė thomasgalliker 10 sausis 2019-01-10 12:34 '19 , 12:34 PM 2019-01-10 12:34

Žr. Kitus klausimus apie žymas arba Užduoti klausimą

"192.102.6.96 - 192.102.6.96"