Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 47

0
votes
answers
30 views
+10

多線程共享本地變量

2

我想充分了解如何創建單獨線程調用一個類實例的同樣的方法可以在該方法實現的局部變量。多線程共享本地變量

例如我有一個單一的方法(劃分)的一類

public class Maths 
{ 
    public int Num1; 
    public int Num2; 

    public void Divide() 
    { 
     for (long i = 0; i < 100000; i++) 
     { 
      Num1 = 2; 
      Num2 = 2; 
      int result = Num1/Num2; 
      Num1 = 0; 
      Num2 = 0; 
     } 
    } 
} 

兩個線程被實例化並稱爲劃分方法如下:

static void Main(string[] args) 
    { 
     Maths m = new Maths(); 

     Task t1 = new Task(() => m.Divide()); 
     Task t2 = new Task(() => m.Divide()); 

     List<Task> tl = new List<Task> { t1, t2 }; 
     Parallel.ForEach(tl, task => task.Start()); 

     Console.ReadLine(); 
    } 

} 

有時,這種代碼運行正常。但是其他時間它將引發就行了dividebyzero錯誤:

INT結果= NUM??1/NUM2;

我的假設是,一個線程被重置NUM1和NUM2零其他線程調用NUM1/NUM2之前。因此造成零除異常。

這將使意義,我應該用一個鎖,但我不明白如何將這些局部變量NUM1和NUM2是在線程之間共享,因爲我的理解是,局部變量不是線程之間共享?

+0

謝謝,現在有道理。 – selams

沙发
0
5

你是正確的,局部變量不是線程(通常,每次方法被調用時,新的一組之間共享它的局部變量執行線程的堆棧中分配的,每個方法調用,這樣局部變量是完全獨立的,並其中一個的修改對其他的沒有影響)。

但是不幸的是Num1Num2不是局部變量,而是fields。同一個類的實例的字段在線程之間共享。

您將需要declate他們這樣讓他們局部變量:

public class Maths 
{ 
    public void Divide() 
    { 
     int Num1; 
     int Num2; 

     for (long i = 0; i < 100000; i++) 
     { 
      Num1 = 2; 
      Num2 = 2; 
      int result = Num1/Num2; 
      Num1 = 0; 
      Num2 = 0; 
     } 
    } 
} 

或者,你coud爲每個線程創建Maths類的單獨的實例,所以每個線程將使用領域Num1和不同Num2Maths類的實例:

static void Main(string[] args) 
{ 
    Maths m1 = new Maths(); 
    Maths m2 = new Maths(); 

    Task t1 = new Task(() => m1.Divide()); 
    Task t2 = new Task(() => m2.Divide()); 

    List<Task> tl = new List<Task> { t1, t2 }; 
    Parallel.ForEach(tl, task => task.Start()); 

    Console.ReadLine(); 
} 
+0

完美的答案和很好的解釋! –

板凳
0
3

由於您使用的是同一個對象,都在同一個任務的更新動作影響其他。

+2

......但只因爲NUM1和NUM2的領域,而不是本地變量,如NUF解釋 –

+0

是,NUF答案更好地解釋它。 – Felipe

0
votes
answers
16 views
+10

CA1800:不要投不必要

-4

,同時實施的一段代碼我得到下面的錯誤CA1800:不要投不必要

「的參數,被鑄造在方法類型‘列表框’多次高速緩存中的‘作爲’操作的結果,或者直接投射以消除冗餘投影類指令。「

代碼

private static void LibrarayMethod(object sender) 
    { 
     try 
     { 
      if (((ListBox)(sender)).SelectedItems.Count > 0) 
      { 
       MainView.GetInstance.Library.SelectedBook = ((ListBox)(sender)).SelectedItems[0].ToString(); 
      } 
     } 
     catch (Exception ex) 
     { 

      Logger.Error("Error in Class - LibrarayMethod() method as ", ex); 
     } 
    } 

請幫助解決這個錯誤。

+0

這不是一個錯誤,它是一個警告。你是否嘗試閱讀'as'運算符或者在C#中進行投射,並用另一個變量替換'(ListBox)(sender)'? – CodeCaster

+1

警告/錯誤很明顯,不是嗎?提取一個保存轉換結果的變量('(ListBox)(sender)'),而不是轉換兩次。 – HimBromBeere

+0

var senderListBox =((ListBox)(sender));如果(senderListBox.SelectedItems' ...等 – ADyson

沙发
0
1

的信息是很清楚的:不是衆多蒙上(ListBox)(sender)把剛剛一個sender as ListBox

private static void LibrarayMethod(object sender) { 
    ListBox box = sender as ListBox; 

    // sender is ListBox and the listbox has selected items 
    if (box != null && box.SelectedItems.Count > 0) 
    MainView.GetInstance.Library.SelectedBook = box.SelectedItems[0].ToString(); 
} 

甚至(短,但是,可能的可讀性):

private static void LibrarayMethod(object sender) { 
    ListBox box = sender as ListBox; 

    if (box?.SelectedItems.Count > 0) 
    box.SelectedItems[0].ToString(); 
} 
+0

我試過這個,它工作正常。 – Karthik

板凳
0
2
var listbox = (ListBox)sender; 
if (listbox.SelectedItems.Count > 0) 
{ 
    MainView.GetInstance.Library.SelectedBook = listbox.SelectedItems[0].ToString(); 
} 
0
votes
answers
24 views
+10

如何從UWP中的另一個正在運行的線程調用UI線程中的方法?

-1

我想從線程內部調用Update(int i)。我曾經使用BeginInvoke(),但它在UWP中不可用。如何從UWP中的另一個正在運行的線程調用UI線程中的方法?

public class Viewmodel 
{ 
Viewmodel() 
{ 
    //start task 
    var mainTask = Task.Factory.StartNew(() => 
    { 
    MyThread(); 
    }); 
} 
private void MyThread() 
{ 
    int i; 
    while(condition) 
    { 
     //do somethings 
     Update(i) 
    } 
} 
private Update(int i) 
{ 
    //do somethings 
} 
} 
沙发
0
0

下面應該工作。

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, 
() => 
{ 
    // update your UI here 
    Update(i) 
}); 
+0

既然提到了原來的問題在視圖模型類中運行,您可以使用'this.Dispatcher'來代替。如果應用程序擁有多個視圖,依靠「MainView」會導致中斷。 –

+0

我會在哪裏使用這段代碼,當我想調用'Update()'時,在Task中? –

+0

@AmirHusseinNargesian你可以把它放在Update()函數中,並在Dispatch處理程序中添加你的邏輯。 – thunderbird

板凳
0
-1

您可以使用下面的代碼來運行代碼:

await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.High/* the rank */, 
() => 
{ 
    // run the code 
}); 

我有另一種方式來做到這一點

await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal /*the rank*/,() => { // run the code }); 

https://stackoverflow.com/a/38175976/6116637

+1

[文檔](https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Core.CoreDispatcherPriority)明確表示不使用「High」值。 –

+0

@ PeterTorr-MSFT Thx,但我想說你可以在此設置排名。 – lindexi

0
votes
answers
23 views
+10

使用ServiceStack.Text反序列化CSV與CustomHeaders:不工作?

1

考慮下面的類:使用ServiceStack.Text反序列化CSV與CustomHeaders:不工作?

class Foo { 
    public string bar { get; set; } 
    public string rab { get; set; } 

    public override string ToString() 
    { 
     return string.Format("[Foo bar={0}, rab={1}]", bar, rab); 
    } 
} 

而下面的代碼:

var csv1 = 
    "bar,rab" + Environment.NewLine + 
    "a,b" + Environment.NewLine + 
    "c,d" + Environment.NewLine + 
    "e,f" + Environment.NewLine; 

var csv2 = 
    "xbar,xrab" + Environment.NewLine + 
    "a,b" + Environment.NewLine + 
    "c,d" + Environment.NewLine + 
    "e,f" + Environment.NewLine; 

Console.WriteLine(CsvSerializer.DeserializeFromString<List<Foo>>(csv1).First()); 

CsvConfig<TMDBEntity>.CustomHeadersMap = new Dictionary<string, string> { 
    {"bar", "xbar"}, 
    {"rab", "xrab"} 
}; 

Console.WriteLine(CsvSerializer.DeserializeFromString<List<Foo>>(csv2).First()); 

它是打印:

[Foo bar=a, rab=b] 
[Foo bar=, rab=] 

,而我希望它打印

[Foo bar=a, rab=b] 
[Foo bar=a, rab=b] 

爲什麼不使用xbar和xrab拾取自定義標題?

ServiceStack.Text版本4.5.14.0

+0

有一個類似的帖子:https://stackoverflow.com/questions/36851708/deserialize-csv-with -customheaders - 使用 - servicestack文本。 statci CsvConfig對象將字典寫入CsvWriter 和CsvReader ,嘗試使用「CcvConfig .CustomHeadersMap = ....」作爲示例。如果不使用TMDBEntity的頭部 –

沙发
0
2

這個問題應該從this commit它可從ServiceStack V5.0.0是現在available on MyGet解決。

注意,你需要爲了配置CsvConfig<Foo>改變如何Foo進行反序列化,如:

CsvConfig<Foo>.CustomHeadersMap = new Dictionary<string, string> { 
    {"bar", "xbar"}, 
    {"rab", "xrab"} 
}; 
0
votes
answers
30 views
+10

Magick.net將PDF轉換爲圖像「無法創建臨時文件」:沒有這樣的文件或目錄@ error/pdf.c/ReadPDFImage/476「

0

我想在控制檯應用程序中使用Magick.net進行渲染來自PDF的圖像,似乎無法解決這個問題。Magick.net將PDF轉換爲圖像「無法創建臨時文件」:沒有這樣的文件或目錄@ error/pdf.c/ReadPDFImage/476「

當打電話 「MagickImageCollection.Read(字節[],設置)」 我總是得到一個

「無法創建臨時文件 '':沒有這樣的文件或目錄@ 錯誤/ pdf.c/ReadPDFImage/476「

異常。

我曾嘗試:

  • bin文件夾放置在x86和64位的DLL的Ghostscript。
  • 使用AnyCPU,86組合,64個版本Magick.net的,與GS
  • 版本設置MagickNET.SetGhostscriptDirectory到Program Files GS bin文件夾
  • 設置MagickNET.SetTempDirectory在C文件夾:/ TEMP並確認我的應用程序可以通過編程方式訪問那裏的文件。
  • 設置MagickAnyCPU.CacheDirectory到一個文件夾在C:/ TEMP

我出的什麼我可以做的想法錯了

using (MagickImageCollection images = new MagickImageCollection()) 
    { 
     // Add all the pages of the pdf file to the collection 
     images.Read(file, settings); 

     switch (orientation) 
     { 
      case Orientation.Horizontal: 
       using (MagickImage image = (MagickImage)images.AppendHorizontally()) 
       { 
        using (MemoryStream ms = new MemoryStream()) 
        { 
         image.Write(ms); 

         return ms.ToArray(); 
        } 

       } 
      case Orientation.Vertical: 
       using (MagickImage image = (MagickImage)images.AppendHorizontally()) 
       { 
        using (MemoryStream ms = new MemoryStream()) 
        { 
         image.Write(ms); 

         return ms.ToArray(); 
        } 
       } 
     } 
    } 
沙发
0
0

我終於設法解決這個問題,我將錯誤的讀取設置傳遞給MagickImageCollection.Read(byte [],settings)。

我告訴Magick讀取與PNG格式的PDF而不是結果寫入PNG ...

MagickReadSettings settings = new MagickReadSettings(); 
settings.Format = MagickFormat.Png; 

我覺得有點傻,但是完全錯誤消息通過我。

0
votes
answers
21 views
+10

手動計時一個C#線程

2

我有一個需要添加一個超長時間運行的線程。我們遇到了一些外部問題,有時會導致該線程無限期地掛在特定的代碼行上。爲了使我們的過程更健壯,我們希望檢測到線程不再主動運行/輪詢並中止線程。這將讓我們清理資源並重新啓動線程。手動計時一個C#線程

添加此功能的首選方法是?

沙发
0
2

你需要兩樣東西:

  1. 其他某些線程,可以做監控和中止(你的「監控」線程)
  2. 一些機制來看看如果懷疑線程仍在工作

在最簡單的版本中,您的可疑線程以可靠的頻率更新當前時間的共享靜態變量。如何適合你的線程的控制流程取決於你(這是很難的部分 - 你通常會用另一個線程來做這種事情)。然後只需要喚醒第二個線程並經常檢查它。如果不是最近一次,請中止該線程。

//suspect thread 
foreach(var thing in whatever) 
{ 
    //do some stuff 
    SomeClass.StaticVariable = DateTime.Now; 
} 

//monitor thread 
while(shouldStillBeWorking) 
{ 
    Thread.Sleep(TimeSpan.FromMinutes(10)); 
    if (DateTime.Now.Subtract(TimeSpan.FromMinutes(15) < SomeClass.StaticVariable) 
     suspectThread.Abort() 
} 
+0

這符合我想要解決問題的方式。很高興看到它由其他人驗證。雖然我可以欣賞Eric的迴應,但它並不適合我的具體應用。多謝你們! – 2010-02-05 15:45:41

板凳
0
6

的優選方法是在它自己的過程運行不可靠的子系統,而不是它自己的線程。這樣,當它表現糟糕時,你可以摧毀整個過程,並讓操作系統清理它留下的任何可怕的混亂。在進程中殺死一個運行不可靠代碼的線程可能會對代碼產生各種令人討厭的副作用,因爲操作系統無法知道哪些資源屬於不良行爲線程以及哪些資源仍在使用。

長話短說:不會與您無法控制的代碼共享進程。

+0

這對我來說並不是真的可行,因爲我需要從此進程中返回結果(它是IBM MQSeries客戶端)。所以這會讓這個單獨的過程難以將數據回傳給我的應用程序。 – 2010-02-02 21:14:30

+0

@Joel:那麼你必須決定你喜歡什麼:健壯和笨重,或脆弱和容易。設計當然是爲您的客戶和利益相關者提供最佳服務的藝術。您的客戶和利益相關者是否認爲產品的耐用性高於或低於產品的易用性?儘管我的答案是 – 2010-02-02 21:30:39

+0

單獨的進程。 @Joel,你爲什麼不直接把最後一次調查的結果告訴你的監測過程(在結束過程之前)?對於進程間通信,我假設你會使用XML-RPC或其他東西。讓嫌疑人處理「奴隸」。 – 2010-02-03 22:24:16

地板
0
0

在您的主應用程序中啓動一個定時器,用於在超時時間結束後中止工作線程。使用工作線程中的回調方法重置計時器。

5106
votes
answers
18 views
+10

Cast int to enum in C#

How can an int be cast to an enum in C#?

up vote 3450 down vote accepted favorite
沙发
+34500
+50

從字符串:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);
// the foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
  throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")

來自int:

YourEnum foo = (YourEnum)yourInt;

更新:

從數字你也可以

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

@FlySwat,如果YourEnum是動態的,只會在運行時知道,我想要的是轉換為Enum? - Shimmy 12年9月19日9:56

請注意,如果您的代碼被混淆,Enum.Parse將無法工作。在混淆後的運行時,將字符串與枚舉名稱進行比較,此時枚舉的名稱不是您期望的那樣。因此,您的解析將在成功之前失敗。 - jropella 2013年4月26日18:03

注意如果您使用上面的“from a string”語法並傳入一個無效的字符串(例如“2342342” - 假設它不是您的枚舉值),它實際上會允許它而不會拋出錯誤!你的枚舉將具有該值(2342342),即使它不是枚舉本身的有效選擇。 - JoeCool 2013年6月25日15:14

我覺得這個答案現在有點過時了。對於字符串,你現在應該使用var result = Enum.TryParse(yourString,out yourEnum)(並檢查結果以確定轉換是否失敗)。 - Justin T Conroy 2013年11月26日21:40

通過向調用添加一個true參數值,也可以使Enum.Parse不區分大小寫:YourEnum foo =(YourEnum)Enum.Parse(typeof(YourEnum),yourString,true); - Erik Schierboom於2014年2月5日12:18

+7960

剛剛施展它:

MyEnum e = (MyEnum)3;

您可以使用Enum.IsDefined檢查它是否在範圍內

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }

請注意,如果使用Flags屬性,則不能使用Enum.IsDefined,並且值是標誌的組合,例如:Keys.L | Keys.Control - 於2009年7月31日凌晨4點49分

關於Enum.IsDefined,請注意它可能是危險的:msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx - adrian 12年4月4日在11:26

我更喜歡這個定義:“返回一個指示指定枚舉中是否存在具有指定值的常量”來自MSDN - Pap 2014年8月18日19:13

...因為你的定義可能會產生誤導,因為你說:“......檢查它是否在範圍內......”這意味著在一系列具有開始和結束限制的數字範圍內...... - Pap 2014年8月18日19:20

@ mac9416我試圖在gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc上給出一個簡潔的例子 - 基本上通過使用IsDefined來檢查輸入值,你會讓自己容易受到以後添加新枚舉值的人的影響,這會通過IsDefined檢查(從那以後)新值存在於新代碼中),但可能不適用於您編寫的原始代碼。因此,明確指定代碼能夠處理的枚舉值更安全。 - 阿德里安18年11月12日22:43

+2210

或者,使用擴展方法而不是單行:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

用法:

Color colorEnum = "Red".ToEnum<Color>();

要么

string color = "Red";
var colorEnum = color.ToEnum<Color>();

為了處理用戶輸入,調用Enum.Parse的重載可能是一個好主意,它允許你指定比較不區分大小寫(即用戶鍵入“red”(小寫)會導致上述代碼崩潰而不進行此更改。) - BrainSlugs83 2013年6月4日20:56

很酷,除了這不是問題。 - nawfal 2013年6月8日21:41

方便,但問題特別詢問有關整數。 - BJury 2015年5月27日10:18

如果字符串是一個整數,這也有效,例如“2” - TruthOf42 16年6月6日19:19

如果enumString為null,則會拋出異常(昨天有類似的問題)。考慮使用TryParse而不是Parse。TryParse還會檢查T是否為Enum Type - Justin Oct 18'16 at 15:03

+1420

我想要得到一個完整的答案,人們必須知道enums如何在.NET內部工作。

事情怎麼樣

.NET中的枚舉是一組將一組值(字段)映射到基本類型(默認值為int)的結構。但是,您實際上可以選擇枚舉映射到的整數類型:

public enum Foo : short

在這種情況下,枚舉被映射到short數據類型,這意味著它將作為short存儲在內存中,並在您投射和使用它時表現為short。

如果從IL的角度來看它,(normal,int)枚舉如下所示:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

這裡應該引起注意的是,它value__與枚舉值分開存儲。Foo上面的枚舉的情況下,類型value__是int16。這基本上意味著只要類型匹配,您就可以在枚舉中存儲您想要的任何內容

在這一點上,我想指出這System.Enum是一個值類型,這基本上意味著BarFlag將佔用內存中的4個字節Foo並將佔用2 - 例如底層類型的大小(它實際上比這更複雜,但是嘿...)。

答案

因此,如果您有一個要映射到枚舉的整數,則運行時只需執行兩項操作:複製4個字節並將其命名為其他名稱(枚舉的名稱)。複製是隱式的,因為數據存儲為值類型 - 這基本上意味著如果使用非託管代碼,則可以簡單地交換枚舉和整數而無需複制數據。

為了使其安全,我認為最佳做法是知道底層類型是相同的或隱式可轉換的,並確保存在枚舉值(默認情況下不會檢查它們!)。

要查看其工作原理,請嘗試以下代碼:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

請注意,施法e2也有效!從上面的編譯器角度來看,這是有道理的:value__字段只用5或6填充,當Console.WriteLine調用時ToString(),名稱e1解析而名稱e2不是。

如果這不是您的意圖,請使用Enum.IsDefined(typeof(MyEnum), 6)以檢查您正在投射的值是否映射到定義的枚舉。

另請注意,我明確了枚舉的基礎類型,即使編譯器實際檢查了這一點。我這樣做是為了確保我不會遇到任何意外。要查看這些意外情況,您可以使用以下代碼(實際上我已經看到這在數據庫代碼中發生了很多):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

我意識到這是一個老帖子,但是你如何在c#中獲得這種知識水平?這是通過閱讀C#規範嗎? - 羅蘭2015年11月15日0:19

@Rolan我有時希望更多的人會這樣問。:-)說實話,我真的不知道; 我試著了解事情是如何運作的,並且只要我能得到它就能獲得信息。我確實閱讀了C#標準,但我也經常用Reflector反編譯代碼(我甚至經常查看x86彙編程序代碼)並做了大量的小實驗。此外,在這種情況下,了解其他語言也有幫助; 我現在已經做了大約30年的CS,並且在某些時候某些事情變得“符合邏輯” - f.ex. 枚舉應該是整數類型,因為否則互操作會破壞(或者你的表現會消失)。 - atlaste 2015年11月15日11:38

我認為正確進行軟件工程的關鍵是了解工作原理。對我而言,這意味著如果您編寫一段代碼,就會知道它大致轉換為f.ex. 處理器操作和內存提取/寫入。如果你問如何達到這個水平,我建議建立一大堆小測試用例,讓它們變得更加艱難,每次嘗試預測結果,然後測試它們(包括反編譯等)。在弄清楚所有細節和所有特徵後,您可以檢查(無聊)標準是否正確。至少,這將是我的方法。 - atlaste 2015年11月15日11:43

很棒的回答,謝謝!在上一個代碼示例中,它會在運行時拋出異常,因為o是一個對象。只要它在短程範圍內,就可以將int變量強制轉換為short。 - gravidThoughts 2016年8月11日17:04

@gravidThoughts謝謝。實際上它是一個拆箱操作,所以它不會像你描述的那樣進行任何隱式轉換。如果您不知道詳細信息,則在C#中有時會導致轉換混亂...無論如何,因為int!= short,它將拋出(取消裝箱失敗)。如果你做對象o =(短)5;,它將起作用,因為那時類型將匹配。它不是關於範圍,而是關於類型。 - atlaste 2016年8月12日6:43

+1100

請看以下示例:

int one = 1;
MyEnum e = (MyEnum)one;
+610

我正在使用這段代碼將int轉換為我的枚舉:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

我覺得這是最好的解決方案。

不適用於旗幟枚舉 - Daniel Fisher lennybacon 2015年3月30日10:09

這很好。我很驚訝在將無效值轉換為int支持的枚舉時沒有異常。 - orion elenzil 2015年11月20日0:50

這實際上並沒有最高級別的答案那麼不同。該答案還討論了在將字符串轉換為Enum類型後使用Enum.IsDefined。因此,即使字符串沒有錯誤地投射,Enum.IsDefined仍將抓住它 - Don Cheadle於17年12月20日16:17

+490

以下是Enums的一個很好的實用程序類

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}
+430

對於數值,這更安全,因為它將返回一個對象,無論如何:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}

這不適用於旗幟枚舉 - Daniel Fisher lennybacon 2015年3月30日10:00

+410

如果您已準備好使用4.0 .NET Framework,那麼新的Enum.TryParse()函數非常有用並且可以與[Flags]屬性配合使用。請參見Enum.TryParse方法(String,TEnum%)

從字符串轉換時這很有用。但是當從int轉換時不是。 - CodesInChaos 2011年11月1日15:08

+310

如果您有一個充當位掩碼的整數並且可以表示[Flags]枚舉中的一個或多個值,則可以使用此代碼將各個標誌值解析為列表:

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

請注意,這假定底層類型enum是帶符號的32位整數。如果它是一個不同的數字類型,你必須更改硬編碼32以反映該類型中的位(或以編程方式派生它Enum.GetUnderlyingType()

這個循環永遠不會終止嗎?flagIterator = 0x00000001,flagIterator = 0x00000002,flagIterator = 0x00000004,...,flagIterator = 0x40000000,flagIterator = 0x80000000,flagIterator = 0x00000000。換句話說,該值將始終低於0x80000000,因為它在位D31 = 1的情況下溢出為零。然後,它永遠保持為0,因為向左移位值0給出0 - Christian Gingras Jan 2 at 5:32

很棒的@christiangingras,謝謝!我已經修改了答案來解釋這個問題,並且應該考慮最高位設置時(即0x80000000 / Int32.MinValue) - Evan M Jan 2 at 15:51

令我感到驚訝的是,這個問題有很多答案,還有一個上升了923次...(使用foreach ofcourse)..我認為,或者至少補充一點,如果你必須迭代一本字典,很可能你是使用它不正確/不恰當..我不得不發表這個評論,因為我看到字典被濫用的方式恕我直言不合適......是的,你可以在很少的情況下迭代字典,而不是查找,這是什麼它是專為..請記住,在想知道如何迭代字典之前。 - Vikas Gupta 2014年9月18日6:52

@VikasGupta當你不知道密鑰是什麼時,你會建議用一組鍵值對做什麼? - - 診斷2015年2月26日22:27

@displayName如果你想對每個鍵值對做一些事情,但沒有引用用於查找值的鍵,你會迭代字典,對吧?我只是指出,有時你可能會想要這樣做,儘管Vikas聲稱這通常是不正確的用法。 - - 2015年10月28日18:01

要說這是不正確的用法意味著有一個更好的選擇。那是什麼選擇? - Kyle Delaney 17年6月20日21:13

VikasGupta是錯誤的,我可以肯定,在非理論場景中經過多年的高性能C#和C ++編程。確實經常出現這樣的情況,即創建字典,存儲唯一的鍵值對,然後迭代這些值,這些值被證明在集合中具有唯一鍵。創建任何進一步的集合是避免字典迭代的一種非常低效且成本高昂的方法。請提供一個很好的替代方案作為澄清您觀點的問題的答案,否則您的評論是非常荒謬的。 - sɐunıɔןɐqɐp8月1日'18時20:53

+250

有時你有一個MyEnum類型的對象喜歡

var MyEnumType = typeof(MyEnumType);

然後:

Enum.ToObject(typeof(MyEnum), 3)
+220

這是一個標誌枚舉感知安全轉換方法:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

現在可以通過約束Enum而不是struct來改進C#7.3,這意味著我們不必依賴於運行時檢查! - 斯科特18年11月9日17:03

+190

在此輸入圖像描述

要將字符串轉換為ENUM或int轉換為ENUM常量,我們需要使用Enum.Parse函數。這是一個YouTube視頻https://www.youtube.com/watch?v=4nhx4VwdRDk ,它實際上演示了字符串,同樣適用於int。

代碼如下所示,其中“red”是字符串,“MyColors”是具有顏色常數的顏色ENUM。

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
+180

稍微遠離原始問題,但我找到了Stack Overflow問題的答案從枚舉中獲取int值非常有用。創建一個帶有public const int屬性的靜態類,允許您輕鬆地收集一堆相關的int常量,然後int在使用它們時不必將它們強制轉換。

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

顯然,一些枚舉類型的功能將會丟失,但是為了存儲一堆數據庫id常量,它似乎是一個非常整潔的解決方案。

枚舉取代了這樣的整數常量的使用,因為它們提供了更多的類型安全性 - Paul Richards 2014年9月1日在7:41

Paul,這是一種收集相關int常量(例如Database id常量)的方法,因此可以直接使用它們,而無需在每次使用時將它們轉換為int。它們的類型是整數,不是例如DatabaseIdsEnum。 - 特德2014年9月1日9:37

我發現至少有一種情況可以無意中繞過枚舉類型的安全性。 - Thierry 2014年9月10日17:33

僅供參考,除了每個文件的多個類的問題之外還有其他含義,所以如果您對這個問題不熟悉,請繼續閱讀。 - 查理2010年1月22日17:23

@ user-12506 - 這在中型到大型開發團隊中效果不佳,需要一定程度的代碼一致性。如前所述,如果您不了解不同的佈局,您可能會發現無法按預期工作的邊緣情況。 - benPearce 2014年2月3日22:28

術語:那些不使用陳述; 他們正在使用指令。另一方面,using語句是與方法體等內的其他語句一起出現的語言結構。例如,使用(var e = s.GetEnumerator()){/ * ... * /}是一個與​​var e = s.GetEnumerator()鬆散相同的語句; 最後嘗試{/ * ... * /} {if(e!= null){e.Dispose(); }。 - Jeppe Stig Nielsen於2017年4月11日21:30

如果任何人都沒有提到這一點,實際上Microsoft也建議在命名空間聲明中使用using語句,在其內部編碼指南中 - user1451111 18年7月27日2:15

+140

這將整數或字符串解析為目標枚舉,在dot.NET 4.0中使用泛型,如上面的Tawani實用程序類中的部分匹配。我用它來轉換可能不完整的命令行開關變量。由於枚舉不能為null,因此您應該在邏輯上提供默認值。它可以像這樣調用:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

這是代碼:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

僅供參考: 問題是有關整數的問題,沒有人提到它也會在Enum.TryParse()中顯式轉換

+130

從字符串:( Enum.Parse已過期,使用Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}

這個問題專門詢問整數。 - BJury 2015年5月27日10:13

請你編輯你的答案,讓每個人都知道Enum.TryParse會處理一個字符串的值或名稱(我無法抗拒) - JeremyWeir 2016年2月10日在5:37

Jeremy,Weir正在努力(無法抗拒)。 - huysentruitw 18年1月29日12:20

Greate,感謝第一個例子!!! - Fox 2月26日12:43

+110

以下是稍微好一點的擴展方法

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }

你也知道它在內部的運作方式嗎? - Boris Callens 2013年3月18日8:12

+100

在我的例子中,我需要從WCF服務返回枚舉。我還需要一個友好的名稱,而不僅僅是enum.ToString()。

這是我的WCF課程。

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

這是從Enum獲取描述的Extension方法。

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

執行:

return EnumMember.ConvertToList<YourType>();
+80

Different ways to cast to and from Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = “north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}

這不是特定於文化的,在某些情況下可能會失敗。culture.CompareInfo.IndexOf(段落,單詞,CompareOptions.IgnoreCase)應該被使用。 - hikalkan 2014年7月22日7:50

為什麼在進行不區分大小寫的字符串比較時要避免使用string.ToLower()?Tl; Dr這是昂貴的,因為新的字符串是“製造的”。 - 利亞姆2016年10月10日10:00

+80

我不知道在哪裡獲得此枚舉擴展的一部分,但它來自stackoverflow。對不起,我很抱歉!但我拿了這個並用Flags修改它的枚舉。對於帶有Flags的枚舉,我這樣做了:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

例:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;

提問者正在尋找包含而不是比較。 - DuckMaestro 2011年7月11日8:05

@DuckMaestro,接受的答案是使用IndexOf實現Contains。所以這種方法同樣有用!此頁面上的C#代碼示例使用string.Compare()。SharePoint團隊的選擇就是! - vulcan raven 2013年1月5日10:07

+60

它可以幫助您將任何輸入數據轉換為用戶所需的枚舉假設你有一個類似於下面的枚舉,默認為int在枚舉的第一個位置添加默認值。當找不到與輸入值匹配時,在helpers方法中使用哪個。

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

注意:這裡我嘗試將值解析為int,因為枚舉是默認的int 如果你定義這樣的枚舉是字節類型。

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

您需要更改輔助方法的解析

int.TryParse(value.ToString(), out  tempType)

byte.TryParse(value.ToString(), out tempType)

我檢查我的方法是否有輸入

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

對不起我的英語不好

你的答案與guptat59完全一樣,但正如他的回答所指出的,這將匹配正則表達式,所以如果你正在測試的字符串包含任何特殊的正則表達式字符,它將不會產生所需的結果。 - 凱西2013年12月9日22:55

這是這個答案的直接副本,並且遇到了與答案中提到的相同的問題 - Liam Oct 10 '16 at 10:04

由於同樣的原因,@ Liam在2017年10月21日4:28給了berniefitz

同意。學習正則表達式 - Jared於17年12月26日5:14

+40

這是一個轉換Int32的擴展方法Enum

即使值高於可能的最大值,它也會遵循按位標誌。例如,如果你有可能性的枚舉12,和4,但int是9,它理解為1在不存在的8這使您可以在代碼更新之前進行數據更新。

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }
+30

在c#中將int轉換為枚舉的簡單明了的方法:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }
+10

您只需使用顯式轉換 Cast int來枚舉或枚舉到int

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((int)Number.three); //Output=3

            Console.WriteLine((Number)3);// Outout three
            Console.Read();
        }

        public enum Number 
        {
            Zero = 0,
            One = 1,
            Two = 2,
            three = 3           
        }
    }
0
votes
answers
13 views
+10

類聲明中的無效標記?

0

我從Fo Dicom開放源代碼庫取得這段代碼,因爲編譯器抱怨說有無效標記,所以代碼沒有編譯。類聲明中的無效標記?

 /// <inheritdoc /> 
     public bool IsEOF => _stream.Position >= _stream.Length; 

在這片碼的錯誤:類

錯誤101無效令牌 '> =',結構或接口成員聲明C:用戶用戶桌面新建文件夾 dicom-development DICOM IO FileByteSource.cs 93 47 DICOM.Desktop

爲什麼會發生這種情況?

+3

你沒有顯示導致錯誤的代碼。 –

+0

對不起,我編輯了另一個錯誤 –

+1

用';'結束語句,並確保您的代碼包含在類中。 –

沙发
0
1

您需要c#7編譯器來編譯該類型的成員聲明。

由於您使用VS 2013,你變老版本的C#編譯器的,不知道這句法和編譯失敗的地方附近=>因爲編譯器總是試圖儘可能多的代碼儘可能男性感。如果你真的有興趣爲什麼在下一次操作中報告錯誤,請抓住你實際最終使用的c#版本的規範,並找出它如何解釋public bool a => b ...

0
votes
answers
16 views
+10

How to make HTTP POST web request

Canonical: How can I make an HTTP request and send some data using the POST method? I can do GET request but have no idea how to make a POST.

0
votes
answers
19 views
+10

我的登錄頁面被瀏覽器驗證框取代

0

我正在開發一個帶有用戶登錄的asp.net web應用程序。它在開發環境上工作得很好。我的登錄頁面被瀏覽器驗證框取代

當用戶只需要訪問成員頁面我的login.aspx文件顯示,但在發佈後,僅顯示僅成員頁面請求瀏覽器本地登錄頁面而不顯示我的login.aspx。請幫我解決這個問題:
enter image description here

+1

你可以直接粘貼內的圖像你的問題?您是否使用HTTP BASIC身份驗證? –

沙发
0
0

它,因爲你使用的是Windows身份驗證,它似乎是你的測試環境是不可能的域(機器或Active Directory)的