Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于调用位置的类型推断_C#_Generics_Type Inference - Fatal编程技术网

C# 基于调用位置的类型推断

C# 基于调用位置的类型推断,c#,generics,type-inference,C#,Generics,Type Inference,我想为泛型类创建一个包装函数,如下所示: public class ColumnData { public static ColumnData<T> Create<T>(string name, int width, ColumnType type, Func<T, string> dataFormater) { return new Colum

我想为泛型类创建一个包装函数,如下所示:

public class ColumnData
{
    public static ColumnData<T> Create<T>(string name, int width, ColumnType type,
                                          Func<T, string> dataFormater)
    {
        return new ColumnData<T>(name, width, type, dataFormater);
    }
}
这里的目的是能够做到:

var myData = new List<MyDataType>();
dataListView.populateFromData(
    myData,
    ColumnData.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString());
var myData=newlist();
dataListView.populateFromData(
我的数据,
Create(“ID”,40,ColumnType.Numeric,x=>x.ID.ToString());
但是,
Create
无法根据预期的签名推断出正确的类型,因此lambda也不知道自己

这是类型推断的一个限制,还是有办法使这个设置工作


注意:如果有必要,我愿意在这个函数调用的某个地方指定实际的数据类型,但我不想为每个
.Create()

指定它。有时,当c#无法推断它的实际类型时,您只需显式地指定泛型类型参数

dataListView.populateFromData(
    myData,
    ColumnData.Create<MyDataType>("ID", 40, ColumnType.Numeric, x => x.ID.ToString());
dataListView.populateFromData(
我的数据,
Create(“ID”,40,ColumnType.Numeric,x=>x.ID.ToString());

正如其他人所解释的,使用您想要的确切语法是不可能的。作为一种解决方法,您可以将键入内容移动到单独的建筑类:

    public class ColumnDataBuilder
    {
        public static ColumnDataBuilder<T> ColumnsFor<T>(IEnumerable<T> data)
        {
            return new ColumnDataBuilder<T>(data);
        }
    }

    public class ColumnDataBuilder<T> : ColumnDataBuilder
    {
        public IEnumerable<T> Data { get; private set; }

        public ColumnDataBuilder(IEnumerable<T> data)
        {
            this.Data = data;
        }
        public ColumnData<T> Create(string name, int width, ColumnType type, Func<T, string> dataFormater)
        {
            return new ColumnData<T>(name, width, type, dataFormater);
        }

        public void populateFromData(params ColumnData<T>[] columns)
        {
            ///...
        }
    }

    public class ColumnData<T>
    {
        public ColumnData(string name, int width, ColumnType type, Func<T, string> dataFormatter)
        {

        }
    }
或者是两个世界中最好的一点:

        var builder = ColumnDataBuilder.ColumnsFor(new List<MyDataType>());
        dataListView.populateFromData(builder.Data, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
使用上面的用法:

        var myData = new List<MyDataType>();
        var builder = ColumnDataBuilder.ColumnsFor(myData);
        dataListView.populateFromData(myData, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
var myData=newlist();
var builder=ColumnDataBuilder.ColumnsFor(myData);
dataListView.populateFromData(myData,builder.Create(“ID”,40,ColumnType.Numeric,x=>x.ID.ToString());

我刚刚找到的一个答案涉及一个别名。我删除了包装器类,并将
Create
方法直接移动到
ColumnData
类中,然后添加:

using ColumnData = ColumnData<MyDataType>;
使用ColumnData=ColumnData;

这允许我访问
ColumnData.Create()
向编译器提供类型提示,而无需在每一行上指定它。我需要在每个文件中创建别名来使用它,但这是一个可行的解决方案。

这正是我所担心的。当数据类型类似于
ShippingReceiptHeader.PendingLineItemDetails
时,它会变得相当痛苦。我认为不是这是一个限制-
myData
告诉您
populateFromData
的泛型类型是
,但这并不强制
ColumnData使用泛型类型。Create
;而是
ColumnData。Create
负责自己的泛型类型,然后编译器检查是否存在
populateFromData
>重载匹配。这并不是说没有一种方法可以通过其他方式实现您想要的,但是…您不能通过«dataListView»@Rawling提供类型参数吗?这很有意义。关于其他方法有什么建议吗?@Jani-没有,因为
dataListView
是一个设计器对象(它继承自ListView),因此它不能是泛型的call,但这没有任何区别。这是我自己提出的一个类似问题,涉及通用实现限制。哦,这真是太聪明了。我刚刚发布了我自己的答案,但我想我会切换到这个问题,因为它更通用,不涉及记住别名(以及别名的含义)。考虑到上一个使用场景,我可以将其进一步简化。我将
ColumnsFor
移动到
dataListView
的类中,并保留
ColumnDataBuilder
类,但删除了除
创建
函数之外的所有内容。其余内容与此无关。我想我可能会失去管理生成的co德,但如果它对你有效,你就更有力量了!这就是为什么我选择了你的答案。:)
        var builder = ColumnDataBuilder.ColumnsFor(new List<MyDataType>());
        dataListView.populateFromData(builder.Data, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
    public class ColumnDataBuilder<T> : ColumnDataBuilder
    {
        public ColumnData<T> Create(string name, int width, ColumnType type, Func<T, string> dataFormater)
        {
            return new ColumnData<T>(name, width, type, dataFormater);
        }
    }

    public class ColumnDataBuilder
    {
        public static ColumnDataBuilder<T> ColumnsFor<T>(IEnumerable<T> data)
        {
            return new ColumnDataBuilder<T>();
        }
    }
        var myData = new List<MyDataType>();
        var builder = ColumnDataBuilder.ColumnsFor(myData);
        dataListView.populateFromData(myData, builder.Create("ID", 40, ColumnType.Numeric, x => x.ID.ToString()));
using ColumnData = ColumnData<MyDataType>;