Aracılığıyla paylaş


CA1045: Türleri başvuruya göre geçirmeyin

TypeName

DoNotPassTypesByReference

CheckId

CA1045

Kategori

Microsoft.Tasarım

Bozan Değişiklik

Bozan

Sebep

Ortak veya korumalı bir yöntemin genel türde bir ref basit tür, bir başvuru türü veya bir değer türü, alan parametresi yerleşik türlerinden biri değil.

Kural Tanımlaması

Türleri başvuruyla geçirme (kullanarak out veya ref) deneyimi işaretçilerle nasıl değer türleri ve başvuru türleri farklı anlama ve birden fazla dönüş değerleri olan metodlarının yönetilmesi gerekir.Ayrıca, arasındaki farkı out ve ref parametreleri değil yaygın anlaşılan.

"Başvuru tarafından" bir başvuru türü gönderildiğinde, parametre nesnesini farklı bir örneğini döndürmek için kullanılacak yöntemi amaçlamaktadır. (Bir başvuru türü başvuruyla geçirme de çift işaretçi işaretçi işaretçi veya çift dolaylı yol kullanarak olarak bilinir.) Varsayılan değer olan "değer" geçti, çağırma kullanarak bir başvuru türü zaten götüren bir parametre nesnesine bir işaretçi alır.İşaretçi, onu işaret ettiği, nesne tarafından değer geçirilir.Referans yeni bir örneğini işaret için işaretçiyi yöntemini değiştiremezsiniz demektir yazın, ancak işaret ettiği nesnesinin içeriğini değiştirebilirsiniz değere göre iletme.Çoğu uygulamalar için bu yeterli ve istediğiniz davranış ortaya çıkarır.

Bir yöntem farklı bir örneğini döndürmesi gerekir, Bunu gerçekleştirmenin yönteminin dönüş değerini kullanın.Bkz: String sınıfı için çeşitli yöntemler dizelerle çalışan ve yeni bir örnek, bir dize döndürür.Bu modeli kullanarak, özgün nesne korunup korunmayacağını karar vermek için arayan bırakılır.

Dönüş değerleri commonplace ve yoğun olarak kullanılan, doğru uygulama olsa da out ve ref Ara tasarım ve becerileri kodlama parametreleri gerektirir.Genel İzleyici ile ana çalışma kullanıcılara beklenemez için kimin tasarım Kütüphane mimarlar out veya ref parametreleri.

[!NOT]

Büyük yapılardır parametreleri ile çalışırken, bu yapılar kopyalamak için gerekli ek kaynaklar değerine göre geçirdiğinizde bir performans etkisi neden olabilir.Bu gibi durumlarda, kullanmayı düşünebilirsiniz ref veya out parametreleri.

İhlallerin Düzeltilmesi

Değer türüne göre neden bu kuralı ihlal düzeltmek için nesneyi onun dönüş değeri olarak geri yöntemi vardır.Yöntem birden çok değer döndürmelidir, değerleri içeren bir nesneyi tek bir örneğini döndürmek için yeniden tasarlamanız.

Başvuru türüne göre neden bu kuralı ihlal düzeltmek için istediğiniz davranışı başvuru yeni bir örneğini döndürmek için olduğundan emin olun.İse, bunu yapmak için yöntem dönüş değerini kullanmanız gerekir.

Uyarılar Ne Zaman Bastırılmalı

Uyarı bu kuraldan bastırmak güvenlidir; Ancak, bu tasarım kullanılabilirlik sorunları neden olabilir.

Örnek

Aşağıdaki kitaplığı kullanıcı geribildirim yanıt üreten bir sınıfın iki uygulamaları gösterir.Birinci (BadRefAndOut) üç dönüş değerlerini yönetmek için kitaplık kullanıcı zorlar.İkinci uygulama (RedesignedRefAndOut) bir container sınıfının bir örneğini döndürerek kullanıcı deneyimini basitleştirir (ReplyData), verileri tek bir birim olarak yönetir.

using System;

namespace DesignLibrary
{
   public enum Actions
   {
      Unknown,
      Discard,
      ForwardToManagement,
      ForwardToDeveloper
   }

   public enum TypeOfFeedback
   {
      Complaint, 
      Praise,
      Suggestion,
      Incomprehensible
   }

   public class BadRefAndOut
   {
      // Violates rule: DoNotPassTypesByReference. 

      public static bool ReplyInformation (TypeOfFeedback input, 
         out string reply, ref Actions action)
      {
         bool returnReply = false;
         string replyText = "Your feedback has been forwarded " + 
                            "to the product manager.";

         reply = String.Empty;
         switch (input)
         {
            case TypeOfFeedback.Complaint:
            case TypeOfFeedback.Praise :
               action = Actions.ForwardToManagement;
               reply = "Thank you. " + replyText;
               returnReply = true;
               break;
            case TypeOfFeedback.Suggestion:
               action = Actions.ForwardToDeveloper;
               reply = replyText;
               returnReply = true;
               break;
            case TypeOfFeedback.Incomprehensible:
            default:
               action = Actions.Discard;
               returnReply = false;
               break;
         }
         return returnReply;
      }
   }

   // Redesigned version does not use out or ref parameters; 
   // instead, it returns this container type. 

   public class ReplyData
   {
      string reply;
      Actions action;
      bool returnReply;

      // Constructors. 
      public ReplyData()
      {
         this.reply = String.Empty;
         this.action = Actions.Discard;
         this.returnReply = false;
      }

      public ReplyData (Actions action, string reply, bool returnReply)
      {
         this.reply = reply;
         this.action = action;
         this.returnReply = returnReply;
      }

      // Properties. 
      public string Reply { get { return reply;}}
      public Actions Action { get { return action;}}

      public override string ToString()
      {
         return String.Format("Reply: {0} Action: {1} return? {2}", 
            reply, action.ToString(), returnReply.ToString());
      }
   }

   public class RedesignedRefAndOut
   {
      public static ReplyData ReplyInformation (TypeOfFeedback input)
      {
         ReplyData answer;
         string replyText = "Your feedback has been forwarded " + 
            "to the product manager.";

         switch (input)
         {
            case TypeOfFeedback.Complaint:
            case TypeOfFeedback.Praise :
               answer = new ReplyData(
                  Actions.ForwardToManagement,
                  "Thank you. " + replyText,
                  true);
               break;
            case TypeOfFeedback.Suggestion:
               answer =  new ReplyData(
                  Actions.ForwardToDeveloper,
                  replyText,
                  true);
               break;
            case TypeOfFeedback.Incomprehensible:
            default:
               answer = new ReplyData();
               break;
         }
         return answer;
      }
   }
}

Aşağıdaki uygulama kullanıcı deneyimini gösterir.Yeniden tasarlanan Kütüphane çağrısı (UseTheSimplifiedClass yöntemi) daha basit bir iştir ve yöntem tarafından döndürülen bilgileri kolayca yönetilebilir.İki yöntem çıktıdan aynıdır.

using System;

namespace DesignLibrary
{
   public class UseComplexMethod
   {
      static void UseTheComplicatedClass()
      {
         // Using the version with the ref and out parameters.  
         // You do not have to initialize an out parameter. 

         string[] reply = new string[5];

         // You must initialize a ref parameter.
         Actions[] action = {Actions.Unknown,Actions.Unknown,
                             Actions.Unknown,Actions.Unknown,
                             Actions.Unknown,Actions.Unknown}; 
         bool[] disposition= new bool[5];
         int i = 0;

         foreach(TypeOfFeedback t in Enum.GetValues(typeof(TypeOfFeedback)))
         {
            // The call to the library.
            disposition[i] = BadRefAndOut.ReplyInformation(
               t, out reply[i], ref action[i]);
            Console.WriteLine("Reply: {0} Action: {1}  return? {2} ", 
               reply[i], action[i], disposition[i]);
            i++;
         }
      }

      static void UseTheSimplifiedClass()
      {
         ReplyData[] answer = new ReplyData[5];
         int i = 0;
         foreach(TypeOfFeedback t in Enum.GetValues(typeof(TypeOfFeedback)))
         {
            // The call to the library.
            answer[i] = RedesignedRefAndOut.ReplyInformation(t);
            Console.WriteLine(answer[i++]);
         }
      }

      public   static void Main()
      {
         UseTheComplicatedClass();

         // Print a blank line in output.
         Console.WriteLine("");

         UseTheSimplifiedClass();
      }
   }
}

Aşağıdaki örnek kitaplık gösterilmektedir nasıl ref parametreleri başvuru türleri için kullanılır ve bu işlevi uygulamak için daha iyi bir yolu gösterir.

using System;

namespace DesignLibrary
{
   public class ReferenceTypesAndParameters
   {

      // The following syntax will not work. You cannot make a 
      // reference type that is passed by value point to a new 
      // instance. This needs the ref keyword. 

      public static void BadPassTheObject(string argument)
      {
         argument = argument + " ABCDE";
      }

      // The following syntax will work, but is considered bad design. 
      // It reassigns the argument to point to a new instance of string. 
      // Violates rule DoNotPassTypesByReference. 

      public static void PassTheReference(ref string argument)
      {
         argument = argument + " ABCDE";
      }

      // The following syntax will work and is a better design. 
      // It returns the altered argument as a new instance of string. 

      public static string BetterThanPassTheReference(string argument)
      {
         return argument + " ABCDE";
      }
   }
}

Aşağıdaki uygulama davranışını göstermek için kitaplıktaki her yöntemini çağırır.

using System;

namespace DesignLibrary
{
   public class Test
   {
      public static void Main()
      {
         string s1 = "12345";
         string s2 = "12345";
         string s3 = "12345";

         Console.WriteLine("Changing pointer - passed by value:");
         Console.WriteLine(s1);
         ReferenceTypesAndParameters.BadPassTheObject (s1);
         Console.WriteLine(s1);

         Console.WriteLine("Changing pointer - passed by reference:");
         Console.WriteLine(s2);
         ReferenceTypesAndParameters.PassTheReference (ref s2);
         Console.WriteLine(s2);

         Console.WriteLine("Passing by return value:");
         s3 = ReferenceTypesAndParameters.BetterThanPassTheReference (s3);
         Console.WriteLine(s3);
      }
   }
}

Bu örnek aşağıdaki çıktıyı üretir.

  

İlgili Kurallar

CA1021: Out parametrelerinden kaçının