2011-07-21 108 views
0

我在教自己C#,所以请原谅我,如果这似乎稍微明显。引用泛型类型中的属性?

我想写一个通用函数,我可以将一个结构数组传入,然后使用该结构的一个属性。我不知道如何在函数中声明一个通用的数据类型,以便我可以以所需的方式引用属性。

也许我所问的可以在代码中更好地传达 - 这是一个非工作函数来说明我正在尝试做什么,它如何触发我的逻辑,它应该工作而不需要真正知道如何写它:

public static int AFunctionIsThis<DataType, int DataType.Value>(DataType passedrecord) 
{ 
    temp = passedrecord.Value * 2 + 1; 

    return temp; 
} 

而我希望能够正常调用它,同时指定要传递的结构的属性。

int NewVariable = AFunctionIsThis<ThisIsAStruct, ThisIsAStruct.AnIntAttribute>(ThisIsADeclaredStruct); 

三江源非常多,

Hanii小狗。

回答

0

(首先,请注意,“属性”这个词从OOP感.NET不同的含义。)

使用Converter<T,int>Action<T,int>代表来获取和设置成员,分别。

例如

public static int AFunctionIsThis<DataType>(DataType passedrecord, Converter<DataType,int> getter) 
{ 
    temp = getter(passedrecord) * 2 + 1; 

    return temp; 
} 

然后调用它

AFunctionIsThis(ThisIsADeclaredStruct, x => x.AnIntProperty); 

如果您还需要设置的值,你可以使用

AFunctionIsThis(ThisIsADeclaredStruct, x => x.AnIntProperty, (x, v) => { x.AnIntProperty = v; }); 

或者做一些魔术Expression<Converter<T>>猛拉出来的成员引用和创建一个匹配的setter。

+0

这就是我已经走了。但是,当我尝试以你所显示的方式调用函数时,这是我得到的:http://img41.imageshack.us/img41/6566/screenshot20110804at084.png –

+0

编辑:好的,我已经得到它了使用此代码可以使用此代码声明以下函数: 'static public void Hierarchical (ref DataType [] Table,Converter ID,Converter SubordinateTo)' 而这调用函数: 'Sort.Hierarchical(ref Categories.Category,ID => Categories.Category [] .ID,SubordinateTo => Categories.Category []。SubordinateTo);' 我知道我必须声明转换为数组的转换项 - 我只是不确定如何^ _^;; 非常感谢! –

+0

@Hanii:其实,认为你需要将数组传递给转换器是你的问题。您的排序功能将拉出阵列中的单个元素并将其传递给转换器,以获取单个ID。尝试'Sort.Hierarchical(Categories.Category,c => c.ID,c => c.SubordinateTo);'数组参数不需要传递给ref,因为数组是一个引用类型。 –

0

Hanii小狗:

简而言之,是的,你应该能够做你正在做的事情,但这里是一个可行的语法:

public static int AFunctionIsThis<T>(T passedRecord) where T : DataType 
{ 
    var temp = passedRecord.Value; 
    return temp; 
} 

public class DataType 
{ 
    public int Value { get; set; } 
} 

希望有所帮助。 Dave

+0

这似乎是实现我想要的最简单的方法 - 但我该如何调用该函数并指定要由Value表示的结构的属性?或者传入的结构必须具有名为“Value”的属性? –

+0

Hanii Puppy:老实说,如果你想保证你可以访问结构的一个属性,使结构实现一个像Guffa建议的接口......无论你传递什么方式,无论你传递什么结构或类将拥有该属性。 – davecoulter

0

你想做什么,是定义一个通用的方法,只接受实现某个接口的T或从某个具有int成员的特定基类派生,该成员称为Value。 e.g:

public interface IClass { int Value{get;set;} } 
    public class ExampleImpl : IClass 
    { 
     int Value{get;set;} 
     /* Additional Members\methods here */ 
    } 
    public class HelperClass 
    { 
    public static int GenMethod<T>(T item) where T:IClass 
    { 
     return item.Value * 2 + 1; 
    } 
    } 
1

你不能指定一个泛型类型应包含的成员,你只能指定通用数据类型。

你会使用其中的属性定义的接口:

public interface IHaveValue { 
    int Value { get; } 
} 

那么你的结构将实现接口,并且可以指定接口为通用数据类型:

public static int AFunctionIsThis<T>(T passedrecord) where T : IHaveValue { 
    return passedrecord.Value * 2 + 1; 
} 

然而,你正在使用它,你根本不需要使用泛型,你可以使用这个接口:

public static int AFunctionIsThis(IHaveValue passedrecord) { 
    return passedrecord.Value * 2 + 1; 
} 

请注意,根本不应该使用结构,而是一个类。结构的实现更加复杂,所以你应该坚持使用类,直到你有一个很好的理由使用结构。

+0

人们仍然问Scala的类型系统是如何比C#/ F#更丰富的:) – Grozz

+0

我一直在大约最后一个小时左右的界面摆弄。 通常调用函数,我得到一个关于没有拳击转换的错误。我知道我应该指定界面中的哪些字段表示结构中的字段,但我不知道该怎么做。当我尝试构建(我希望复制粘贴错误)时,该错误在leu中消失,出现在接口中声明的每个变量下出现的错误,就像读取“Interfaces can not contain fields”(接口不能包含字段)一样。 –

+0

对,一个接口不能有字段,所以你需要使用属性。我纠正了上面的代码。接口和实现类型之间的标识是通过名称进行的,也就是说,只需在接口中创建一个与其名称相同的属性即可。 – Guffa