'T' টাইপের মান রূপান্তর করা যায় না


146

এটি সম্ভবত আশ্চর্যজনক প্রশ্ন, তবে গুগল আশ্চর্যরূপে কোনও উত্তর দেয় নি।

আমার এটি বরং কৃত্রিম পদ্ধতি রয়েছে

T HowToCast<T>(T t)
{
    if (typeof(T) == typeof(string))
    {
        T newT1 = "some text";
        T newT2 = (string)t;
    }

    return t;
}

একটি সি ++ ব্যাকগ্রাউন্ড থেকে আসার আমি এটি কাজ করার আশা করেছি। যাইহোক, এটি উপরোক্ত উভয় কার্যভারের জন্য "স্পষ্টভাবে 'T' টাইপকে স্ট্রিংয়ে রূপান্তর করতে পারে না" এবং "টাইপ 'T' কে স্ট্রিংয়ে রূপান্তর করতে পারে না" সংকলন করতে ব্যর্থ হয়েছে।

আমি হয় ধারণামূলকভাবে ভুল কিছু করছি বা কেবল ভুল বাক্য গঠন করছি। দয়া করে আমাকে এটিকে সাজানোর জন্য সহায়তা করুন।

ধন্যবাদ!


20
আইএমও, যদি আপনি আপনার জেনেরিক কোডে প্রকার পরীক্ষা করে থাকেন তবে জেনেরিকগুলি সম্ভবত আপনার সমস্যার সঠিক সমাধান নয়।
অস্টিন স্যালোনেন

typeof(T) == typeof(string)সংকলন-সময় নয়, অভিব্যক্তিটি রানটাইমে সমাধান করা হয়। সুতরাং ব্লকের নিম্নলিখিত লাইনটি অবৈধ।
স্টিভ গুইদি

8
(টি) রূপান্তর করুন han চেঞ্জটাইপ (নতুন টি 1, টাইপফ (টি))
বনবিপিহ

2
@vsapiha, কেবল তখনই কাজ করে যদি অবজেক্টটি IConvertible কার্যকর করে। মিষ্টি থাকলেও হয়।
ওফ্লাক করুন

উত্তর:


285

যদিও এটি একটি এর ভিতরে ifব্লক, কম্পাইলার জানে না যে Tহয় string
অতএব, এটি আপনাকে castালতে দেয় না। (একই কারণে যে আপনি কাস্ট পারে না DateTimeকরার string)

আপনাকে কাস্ট করতে হবে object(যার মধ্যে Tকেউ কাস্ট করতে পারে) এবং সেখান থেকে string(যেহেতু objectকাস্ট করা যেতে পারে string)।
উদাহরণ স্বরূপ:

T newT1 = (T)(object)"some text";
string newT2 = (string)(object)t;

2
এইটা কাজ করে! আমি অনুমান করছি যে দ্বিতীয়টির মতো টিও নতুন টি 2 = (টি) (অবজেক্ট) টি হওয়া উচিত; যদিও এটি কোনও বিকল্প নেই।
অ্যালেক্স

2
সংযোজন: সি ++ টেমপ্লেটগুলি মূলত পরিবর্তিত সঠিক মানগুলির সাথে সংকলন সময়ে কাটা এবং পেস্ট করা হয় are সি # তে প্রকৃত জেনেরিক টেম্পলেট (এটির "ইনস্ট্যান্টেশন" নয়) সংকলনের পরে বিদ্যমান এবং সুতরাং নির্দিষ্ট ধরণের সীমানা জুড়ে অবশ্যই জেনেরিক হতে হবে (পুণ্য ক্ষমা করে)।

(STRING) (বস্তু) টি; যদিও এখানে কিছুই করে না, পাশাপাশি এটি ছেড়ে দিতে পারে, (স্ট্রিং) (অবজেক্ট) যা
ডগজেট

6
শুধু "স্ট্রিং হিসাবে" ব্যবহার করে কেন কাস্ট করবেন না? উদাহরণস্বরূপ, এটির সূক্ষ্ম সংকলন (আমি আক্ষরিক অর্থে এটি ত্রুটি ছাড়াই সংকলন করেছি) যখন ব্যবহারকারী ডেফাইনডভ্যালু টাইপ করা হয় T:var isBlank = (userDefinedValue is string) && String.IsNullOrWhiteSpace(userDefinedValue as string);
ট্রিইঙ্কো

1
এটি সংকলক ডিজাইনারদের দ্বারা একটি ভুল বলে মনে হয়। যদি সমস্ত টি অবজেক্টে অবলম্বনভাবে কাস্ট করা যায় এবং সমস্ত বস্তুকে স্পষ্টভাবে স্ট্রিংয়ে ফেলে দেওয়া যেতে পারে তবে সেখানে একটি ট্রানজিটি নিয়ম থাকা উচিত যে টি স্পষ্টভাবে স্ট্রিংয়ে ফেলে দেওয়া যেতে পারে। আপনি যদি ভুলভাবে কাস্ট সম্পাদন করেন তবে রানিমের ত্রুটি ঘটতে হবে।
পি.ব্রায়ান.ম্যাকি

10

উভয় লাইনেই একই সমস্যা রয়েছে

T newT1 = "some text";
T newT2 = (string)t;

সংকলকটি জানে না যে টি একটি স্ট্রিং এবং এটি কীভাবে বরাদ্দ করা যায় তা জানার কোনও উপায় নেই। আপনি যেহেতু চেক করেছেন আপনি কেবল এটির সাথে জোর করতে পারেন

T newT1 = "some text" as T;
T newT2 = t; 

আপনার টি কাস্ট করার দরকার নেই কারণ এটি ইতিমধ্যে একটি স্ট্রিং, এছাড়াও সীমাবদ্ধতা যুক্ত করতে হবে to

where T : class

2
ভুল। এটি সংকলন করবে না। আমার উত্তর দেখুন।
স্ল্যাक्स

2
ঠিক জরিমানা সংকলন (যেদিকে সেখানে, যোগ করা হয়েছে যে আমি পোস্ট করার কয়েক সেকেন্ড পরে, সম্ভবত এটি মিস হয়ে গেছে)। ওফ এনএম কাস্ট পরিবর্তন করতে ভুলে গেছে
ডগজেট

2

আমি অনুরূপ কোড জানি যে জেনেরিক পার্সারদের থেকে ওপ এই প্রশ্নে পোস্ট করেছে। একটি কার্যকারিতা দৃষ্টিকোণ থেকে, আপনি ব্যবহার করা উচিত Unsafe.As<TFrom, TResult>(ref TFrom source), খুঁজে পাওয়া যেতে পারে যা System.Runtime.CompilerServices.Unsafe NuGet প্যাকেজ। এই পরিস্থিতিতে এই ধরণের মানের জন্য বক্সিং এড়ানো হয়। আমি আরও মনে করি যে Unsafe.Asদুটি বার usingালাই (ব্যবহার (TResult) (object) actualString) করার চেয়ে JIT দ্বারা উত্পাদিত কম মেশিন কোডের ফলস্বরূপ , তবে আমি এটি পরীক্ষা করে দেখিনি।

public TResult ParseSomething<TResult>(ParseContext context)
{
    if (typeof(TResult) == typeof(string))
    {
        var token = context.ParseNextToken();
        string parsedString = token.ParseToDotnetString();
        return Unsafe.As<string, TResult>(ref parsedString);
    }
    else if (typeof(TResult) == typeof(int))
    {
        var token = context.ParseNextToken();
        int parsedInt32 = token.ParseToDotnetInt32();
        // This will not box which might be critical to performance
        return Unsafe.As<int, TResult>(ref parsedInt32); 
    }
    // other cases omitted for brevity's sake
}

Unsafe.As JIT দ্বারা দক্ষ মেশিন কোড নির্দেশাবলীর সাথে প্রতিস্থাপন করা হবে, আপনি অফিসিয়াল কোরএফএক্স রেপোতে দেখতে পারেন:

অনিরাপদ এর সোর্স কোড .এএস


1

আপনি যদি সুস্পষ্ট প্রকারের জন্য পরীক্ষা করে দেখছেন তবে আপনি কেন এই পরিবর্তনগুলি T'গুলি হিসাবে ঘোষণা করছেন ?

T HowToCast<T>(T t)
{
    if (typeof(T) == typeof(string))
    {
        var newT1 = "some text";
        var newT2 = t;  //this builds but I'm not sure what it does under the hood.
        var newT3 = t.ToString();  //for sure the string you want.
    }

    return t;
}

6
দ্বিতীয় লাইন প্রকারের একটি পরিবর্তনশীল তৈরি করে T
স্ল্যাक्स

আপনি জিজ্ঞাসা কেন প্রকারটি পরীক্ষা? ধরুন আপনার কাছে একটি বেস ক্ষেত্রের টাইপ রয়েছে যা objectমানগুলি সঞ্চয় করে , উদ্ভূত প্রকারের সাথে stringমানগুলি সঞ্চয় করে । মনে করুন এই ক্ষেত্রগুলির একটি "ডিফল্টআইফনটপ্রাইভেটড" মানও রয়েছে তাই আপনাকে ব্যবহারকারী-প্রদত্ত মান (যা কোনও বস্তু বা স্ট্রিং বা এমনকি একটি সংখ্যার আদিম হতে পারে) সমতুল্য কিনা তা পরীক্ষা করে দেখতে হবে default(T)। স্ট্রিংকে একটি বিশেষ ক্ষেত্রে হিসাবে বিবেচনা করা যেতে পারে যেখানে খালি / সাদা স্থানের স্ট্রিংটি ডিফল্ট (টি) এর মতোই হয়, তাই আপনি যাচাই করতে পারেন T userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace(userValue as string);
ট্রায়ঙ্কো

0

আপনার ক্লাস এবং আপনার পদ্ধতি উভয়ের জন্য জেনেরিক ঘোষণা থাকলে আপনিও এই ত্রুটিটি পাবেন। উদাহরণস্বরূপ নীচে প্রদর্শিত কোডটি এই সংকলন ত্রুটি দেয়।

public class Foo <T> {

    T var;

    public <T> void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException {
        this.var = cls.newInstance();
    }

}

এই কোডটি সংকলন করে (নোট টি পদ্ধতির ঘোষণা থেকে সরানো হয়েছে):

public class Foo <T> {

    T var;

    public void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException {
        this.var = cls.newInstance();
    }

}

-5

এই লাইনটি পরিবর্তন করুন:

if (typeof(T) == typeof(string))

এই লাইনের জন্য:

if (t.GetType() == typeof(string))

1
তারা একই
বিগ ওয়ার্ল্ড 12

উভয়ই একই ... কেবল শ্রেণিবদ্ধের API গুলি ব্যবহার করে ভাষা কীওয়ার্ড ব্যবহার করা।
আব্দুলহামেদ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.