是否可以在C#中的方法中定义本地结构?

时间:2010-11-17 15:22:32

标签: c#

常见的编程最佳实践之一是“将变量定义为尽可能接近它们的位置”。

我经常使用结构来创建几乎在某些地方自我记录的代码。但是,C#强迫我在方法之外定义结构。这打破了上述最佳实践 - 它基本上为整个类创建了一个不需要的全局变量类型。

是否可以在方法中定义局部结构,就像局部变量一样,如果没有,你能给我一个窗口,说明C#设计者决定阻止它的原因吗?

用例

我正在将电子表格的一部分转换为C#代码。我想在方法中使用本地结构以有组织的方式存储临时信息,而不必求助于数百个全局范围的单独变量。

更新 - C#7.0可能具有此功能!

截至2016年8月,显然,这将是C#7.0中的一个功能。

所以C#编译团队同意了 - 哇!

10 个答案:

答案 0 :(得分:25)

我认为不允许在方法中定义命名类型。至于为什么,我将不得不推测。如果某种类型不会在外部使用,那么它的存在可能是不合理的。

但是,您可以在方法中定义匿名类型变量。它有点像结构。妥协。

public void SomeMethod ()
{
    var anonymousTypeVar = new { x = 5, y = 10 };
}

答案 1 :(得分:7)

这有点晚了,但这是我的列表解决方案 - 使用匿名变量作为方法中的结构:

var list = new[] { new { sn = "a1", sd = "b1" } }.ToList(); // declaring structure
list.Clear();                                               // clearing dummy element
list.Add(new { sn="a", sd="b"});                            // adding real element
foreach (var leaf in list) if (leaf.sn == "a") break;       // using it

匿名元素(sn和sd)在某种程度上是只读的。

答案 2 :(得分:6)

您可以使用anonymous types执行此类操作。 MSDN示例如下:

var v = new { Amount = 108, Message = "Hello" };

var productQuery = 
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

答案 3 :(得分:3)

不,这是不可能的。如果您使用的是.net 4.0,则可以使用Tuple<T1, ..., Tn>复制此类内容。

我没有看到你需要这样一个结构的原因 - 只使用带有说话名字的变量,这根本不应该是任何问题。结合使用类名的显式声明,几乎没有模糊性的空间。

答案 4 :(得分:3)

从C#7.0开始,如果要使用带有命名字段的轻量级数据结构,则可以使用value tuples。它们不仅可以在方法内部局部使用,还可以在参数,返回值,属性,字段等中使用。您可以使用local functions在某种程度上模拟结构方法。

var book = (id: 65, pageCount: 535);        // Initialization A
(int id, int pageCount) book2 = (44, 100);  // Initialization B
Console.WriteLine($"Book {book.id} has {book.pageCount} pages.");

(int id, int pageCount) = book;  // Deconstruction into variables
Console.WriteLine($"Book {id} has {pageCount} pages.");

book的类型为System.ValueTuple<int, int>(通用结构)。

答案 5 :(得分:1)

您可以在方法中定义匿名类型并使用它。匿名类型将是只读的,因此它可以获得结构所需的不变性。它不会显式是一个结构,但它将完全定义并包含在您的方法中。

var myLocalType = new 
    {
        SomeValue = "Foo",
        SomeId = 14
    };

答案 6 :(得分:1)

它不是一个结构,但mayme var可以帮助你在这里吗?

var person = new {Name= "John", City = "London"};

它是强类型的,因此它将被编译时检查

答案 7 :(得分:1)

您可以在c#4.0中创建动态类型来完成此任务,但它并不完全符合您的要求。

但是我认为,定义变量的最大值接近于它们的使用位置意味着将变量引入程序流的位置,而不是声明类型的位置。我相信大多数类型都有一些重用的能力,在方法类型中创建限制了您创建可在公共数据上运行的可重用代码块的能力。

答案 8 :(得分:1)

现在,您还可以使用命名的tupple:https://docs.microsoft.com/en-us/dotnet/csharp/tuples

答案 9 :(得分:0)

不,这是不可能的。什么是实际应用?仅在单个方法中使用结构的频率有多高。微软可能没有看到实现此功能的令人信服的理由。在它可能有用的情况下,我们有匿名类型和匿名方法。