简体   繁体   English

返回简单类型的泛型方法

[英]Generic methods returning simple types

Ok, I've got a bit of code that I don't like very much. 好的,我有一些我不太喜欢的代码。 Given that I didn't write it and merely inherited it, it occurs to me that I could clean it up a little. 鉴于我没有写它而只是继承它,我发现我可以将它清理一下。 Basically, we have an object for settings that is persisted with NHibernate. 基本上,我们有一个NHibernate持久设置的对象。 I won't bore you with the implementation details except to say that it contains a dictionary that has the actual values we're keeping in the database. 我不会厌倦了实现细节,只是说它包含一个字典,其中包含我们在数据库中保存的实际值。

Our typical property implementation looks like this: 我们典型的属性实现如下所示:

public string MyDumbProperty
{
get { return GetStringValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}

Now, it's probably obvious from the implementation above that we have separate Getxxxx methods for each of the types we return (strings, ints, longs, floats, etc.), with the second parameter being a default value. 现在,从上面的实现可以明显看出,对于我们返回的每个类型(字符串,整数,长整数,浮点数等),我们都有单独的Getxxxx方法,第二个参数是默认值。 What I want is to be able to do something like the following: 我想要的是能够做如下的事情:

public string MyDumbProperty
{
get { return GetValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}

I have a couple of reasons for wanting to do this. 我有几个理由想要这样做。 The big one is that I have a personal dislike of methods named based on what types of parameters they take. 最重要的一点是,我个人不喜欢根据他们采用的参数类型命名的方法。 The second is that I'd like to make a resharper template for this crap. 第二个是我想为这个垃圾制作一个resharper模板。 Then I could just fill in the name of the property and the type and be done (presuming that resharper could give a reasonable default value for the type). 然后我可以填写属性的名称和类型并完成(假设resharper可以为该类型提供合理的默认值)。

I had thought of making a generic method GetValue that returned a T, but I'm not sure how I need to set up the generic constraints so this is doable. 我曾想过制作一个返回T的泛型方法GetValue,但我不确定如何设置泛型约束,所以这是可行的。 The types being returned from this will all be basic types (strings, ints, etc). 从这里返回的类型都是基本类型(字符串,整数等)。 There are a couple that return arrays, but I could always do something different on those. 有一对返回数组,但我可以总是做些不同的事情。 This isn't a high priority issue, by any means, but it annoys me every time I see it. 无论如何,这不是一个高度优先的问题,但每次看到它都会让我很烦。 I just think there should be a better way to do this. 我认为应该有更好的方法来做到这一点。

I suppose a first step would be to just rename the various methods. 我想第一步就是重命名各种方法。 Since they vary on what type is being passed for the default in the second parameter, I could at least coerce them to the same name. 由于它们在第二个参数中传递的默认值类型不同,我至少可以将它们强制为相同的名称。 But I could I do better than that? 但我能做得更好吗? It would be great if I could get rid of the multiple bits of repetitive code in each method that are only different in terms of the datatype being used (TryParse in all the numeric ones). 如果我能够摆脱每种方法中多个重复代码的位置,那将是很好的,这些代码只是在使用的数据类型方面不同(TryParse在所有数字类型中)。

I think you might be able to get away with a generic method if the guts of it aren't too complicated. 我认为如果它的内容不太复杂,你可能能够使用泛型方法。 For example, maybe something like this: 例如,可能是这样的:

public T GetValue<T>(string name, T ifNull) where T : IConvertible
{
    string value = GetProperty(name);
    if (value == null)
        return ifNull;
    try
    {
        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch
    {
        return ifNull;
    }
}

For arrays, you might need a GetArrayValue function that does something different. 对于数组,您可能需要GetArrayValue函数来执行不同的操作。

You can use default(T) to get the default value of a type. 您可以使用default(T)来获取类型的默认值。

public T Get<T>(string propertyName)
{
    object obj;
    if (propertyBag.TryGetValue(propertyName, out obj)) {
        return (T)obj;
    }
    if(typeof(T) == typeof(string)) {
        return String.Empty;
    }
    return default(T);
}

UPDATE UPDATE

As an alternative you could have two overloads, one accepting an explicit default value. 作为替代方案,您可以有两个重载,一个接受显式默认值。

public T Get<T>(string propertyName)
{
    return Get<T>(propertyName, default(T));
}

public T Get<T>(string propertyName, T defaultValue)
{
    object obj;
    if (propertyBag.TryGetValue(propertyName, out obj)) {
        return (T)obj;
    }
    return defaultValue;
}

The great thing about .net generics is that they can be implicitly used when it is clear which parameters they represent. 关于.net泛型的好处是,当它们清楚表明它们代表哪些参数时,可以隐式使用它们。 Not sure about the grammar on that sentence, but a lot surer of that it's possible based on using it a lot.. 不确定那个句子上的语法,但很可靠的是,它可以基于使用它很多..

eg for the GetValue: 例如,对于GetValue:

 public T GetValue<T>(string PropertyName, T DefaultValue)
 {

 }

 .... return GetValue("Prop1", 4); //T = int
 .....return GetValue("Prop2", string.Empty) //T= string
 //for nullable times, you can always include the generic parameter
 GetValue<int[]>("Prop3",null);
 //or by 'strongly typing' the null value:
 GetValue("Prop3", (int[])null); //for set this isn't a problem, since 'value' already is strongly typed

the same for setting 设置相同

public void SetValue<T>(string PropertyName, T Value)
{
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM